adding different layouts for every view in recyclerview - android

I am making an android chat app. I have a recyclerview to show messages. i have two different layouts for messages, one for sent and one for received. my recyclerview doesnt throw any error but is doesnt show anything on the screen.
This is my adapter class :
public class ChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Chat> items;
private final int USER = 1, CONTACT = 2;
// Provide a suitable constructor (depends on the kind of dataset)
public ChatAdapter(List<Chat> items) {
this.items = items;
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return this.items.size();
}
#Override
public int getItemViewType(int position) {
if(items.get(position).getType()==1)
return USER;
else
return CONTACT;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
RecyclerView.ViewHolder viewHolder;
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
switch (viewType){
case USER:
View v1 = inflater.inflate(R.layout.chat_item_user, viewGroup, false);
viewHolder = new ViewHolder1(v1);
break;
default:
View v2 = inflater.inflate(R.layout.chat_item_contact, viewGroup, false);
viewHolder = new ViewHolder1(v2);
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
switch (viewHolder.getItemViewType()) {
case USER:
ViewHolder1 vh1 = (ViewHolder1) viewHolder;
configureViewHolder1(vh1, position);
break;
default:
ViewHolder2 vh2 = (ViewHolder2) viewHolder;
configureViewHolder2(vh2, position);
break;
}
}
public void configureViewHolder1(ViewHolder1 viewHolder, int position){
Chat chat = items.get(position);
viewHolder.getTv().setText(chat.getMsg());
}
public void configureViewHolder2(ViewHolder2 viewHolder, int position){
Chat chat = items.get(position);
viewHolder.getTv().setText(chat.getMsg());
}
}
This is my Chat class:
public class Chat {
private int type;
private String msg;
private long time;
public Chat(int type,long time,String msg){this.type = type; this.msg = msg; this.time = time;}
public int getType(){return type;}
public void setType(int type){this.type = type;}
public String getMsg(){return msg;}
public void setMsg(String msg){this.msg = msg;}
public long getTime(){return time;}
public void setTime(long time){this.time = time;}
}
This my layout containing the recylcerview :
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ChatActivity">
<TextView
android:id="#+id/textView3"
android:layout_width="368dp"
android:layout_height="59dp"
android:layout_marginEnd="9dp"
android:layout_marginStart="7dp"
android:layout_marginTop="16dp"
android:background="#android:color/holo_green_light"
android:text="TextView"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="368dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_height="394dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView3" />
<EditText
android:id="#+id/editText8"
android:layout_width="325dp"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginStart="8dp"
android:layout_marginTop="1dp"
android:ems="10"
android:inputType="textMultiLine"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/imageButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/recyclerView" />
<ImageButton
android:id="#+id/imageButton"
android:layout_width="53dp"
android:layout_height="54dp"
android:scaleType="fitCenter"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/recyclerView"
app:srcCompat="#drawable/logo_arrow" />
These are my two layouts:
a. chat_item_contact
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView5"
android:layout_width="323dp"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="45dp"
android:layout_marginTop="16dp"
android:background="#android:color/holo_green_light"
android:paddingLeft="10dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
b. chat_item_user
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView4"
android:layout_width="329dp"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginEnd="48dp"
android:layout_marginStart="7dp"
android:layout_marginTop="7dp"
android:background="#android:color/holo_green_light"
android:paddingLeft="10dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

I've done something similar, you should focus mostly on getItemViewType
Here is how I do (also I suggest you to use RecyclerView instead of ListView)
#Override
public int getItemViewType(int position){
if (/*your condition based on message received or sent*/) {
return VIEW_MESSAGE_RECEIVED;
}
else {
return VIEW_MESSAGE_SENT;
}
}
After, you just check what getItemViewType has returned
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_MESSAGE_RECEIVED) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.chat_message_item_received, parent, false);
return new ChatAdapter.MyViewHolder(view);
}else {
View eventDataView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.chat_message_item_sent, parent, false);
return new ChatAdapter.MyViewHolder(view);
}
}

Try this code..
remove listitem null check because once value is assign after that it not getting null.
add also add one more things if one layout is show than other is gone at time two layout not show to good..
if (currentChat.getType() == 1) {
listItem1 = LayoutInflater.from(context).inflate(R.layout.chat_item_user, parent, false);
listItem1.setVisibility(View.VISIBLE);
listItem2.setVisibility(View.GONE);
} else {
listItem2 = LayoutInflater.from(context).inflate(R.layout.chat_item_contact, parent, false);
listItem2.setVisibility(View.VISIBLE);
listItem1.setVisibility(View.GONE);
}

Related

trying to iterate spinners RecycleView by clicking a button miss few items

PLEASE READ THE EDIT SECTION BELLOW
I have a Spinners Recyclerview (list) I want to iterate after clicking a button(finishBtn).
in order to get the selected results entered by the user, I try to iterate the list using list.findViewHolderForAdapterPosition.
The size of the list is supposed to be 6 (by viewing Recyclerview I can see all 6) but when I try to iterate, the size is smaller than what actually there is. (instead of 6 the list.getChildCount() is only 3).
Fragment:
public class FragmentUserDetails extends Fragment {
Button finishBtn;
LinkedHashMap<String, ArrayList<String>> detailsQuestions;
DetailsViewModel detailsViewModel;
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
detailsViewModel = new ViewModelProvider(this).get(DetailsViewModel.class);
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_user_details, container, false);
detailsQuestions =getQuestions();
Log.d("TAG", "size: "+detailsQuestions.size());
RecyclerView list = view.findViewById(R.id.details_list_rv);
list.setHasFixedSize(true);
list.setLayoutManager(new LinearLayoutManager(getContext()));
DetailsAdapter detailsAdapter = new DetailsAdapter(this);
list.setAdapter(detailsAdapter);
finishBtn = view.findViewById(R.id.userDetails_next_btn);
((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(false);
finishBtn.setOnClickListener(v -> {
Log.d("TAG", ""+list.getChildCount());
for (int i = 0; i < list.getChildCount(); i++) {
DetailsHolder holder = (DetailsHolder) list.findViewHolderForAdapterPosition(i);
if (holder!=null) {
String question = (String) detailsQuestions.keySet().toArray()[i];
Log.d("TAG", "The answer for " +question+"is :"+ holder.questionSp.getSelectedItem().toString());
}
}
Intent intent = new Intent(getContext(), MainActivity.class);
startActivity(intent);
getActivity().finish();
});
return view;
}
interface OnItemClickListener {
void onItemClick(int position);
}
public LinkedHashMap<String, ArrayList<String>> getQuestions() {
ArrayList<Detail> arrayList = detailsViewModel.getDetails();
detailsQuestions = new LinkedHashMap<>();
for (Detail detail : arrayList) {
detailsQuestions.put(detail.getQuestion(), detail.getAnswers());
}
return detailsQuestions;
}
}
Adapter:
class DetailsAdapter extends RecyclerView.Adapter<DetailsHolder> {
private final FragmentUserDetails fragmentUserDetails;
FragmentUserDetails.OnItemClickListener listener;
public DetailsAdapter(FragmentUserDetails fragmentUserDetails) {
this.fragmentUserDetails = fragmentUserDetails;
}
public void setOnItemClickListener(FragmentUserDetails.OnItemClickListener listener) {
this.listener = listener;
}
#NonNull
#Override
public DetailsHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = fragmentUserDetails.getLayoutInflater().inflate(R.layout.details_list_row, parent, false);
DetailsHolder detailsHolder = new DetailsHolder(view, listener);
return detailsHolder;
}
#Override
public void onBindViewHolder(#NonNull DetailsHolder detailsHolder, int position) {
if(fragmentUserDetails.detailsQuestions.size()!=0) {
String detail = (String) fragmentUserDetails.detailsQuestions.keySet().toArray()[position];
fragmentUserDetails.detailsQuestions.get(detail).add(0,detail);
String[] array = fragmentUserDetails.detailsQuestions.get(detail).toArray(new String[0]);
ArrayAdapter adapter = new ArrayAdapter<String>(fragmentUserDetails.getContext(), R.layout.spinner_item, array){
#Override
public boolean isEnabled(int position) {
if (position == 0) {
return false;
} else {
return true;
}
}
#Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
View view = super.getDropDownView(position, convertView, parent);
TextView tv = (TextView) view;
if (position == 0) {
// Set the hint text color gray
tv.setTextColor(Color.GRAY);
} else {
tv.setTextColor(Color.WHITE);
}
return view;
}};
detailsHolder.questionSp.setAdapter(adapter);
adapter.setDropDownViewResource(R.layout.spinner_item);
}
}
#Override
public int getItemCount() {
return fragmentUserDetails.detailsQuestions.size();
}
}
Holder:
class DetailsHolder extends RecyclerView.ViewHolder {
Spinner questionSp;
public DetailsHolder(#NonNull View itemView, FragmentUserDetails.OnItemClickListener listener) {
super(itemView);
questionSp = itemView.findViewById(R.id.listrow_question_sp);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = getAdapterPosition();
listener.onItemClick(pos);
}
});
}
}
details_list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true">
<Spinner
android:id="#+id/listrow_question_sp"
android:layout_width="409dp"
android:layout_height="90dp"
android:layout_weight="1"
android:clickable="true"
android:drawablePadding="14dp"
android:focusable="true"
android:maxLines="1"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:spinnerMode="dialog"
android:textSize="18sp"
android:theme="#style/mySpinnerItemStyle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
fragment_user_details.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
tools:context=".details.FragmentUserDetails">
<ImageView
android:id="#+id/userDetails_img_main"
android:layout_width="306dp"
android:layout_height="160dp"
android:layout_marginTop="30dp"
android:src="#drawable/logo__nobg_2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/homeScr_text_title"
android:layout_width="350dp"
android:layout_height="90dp"
android:layout_marginTop="16dp"
android:fontFamily="sans-serif-light"
android:gravity="center"
android:text="Please enter the following details:"
android:textColor="#color/white"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.491"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/userDetails_img_main" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/details_list_rv"
android:layout_width="402dp"
android:layout_height="211dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/homeScr_text_title" />
<com.google.android.material.button.MaterialButton
android:id="#+id/userDetails_next_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginTop="3dp"
android:fontFamily="sans-serif-black"
android:text="NEXT"
android:textSize="20sp"
app:cornerRadius="35dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/details_ti" />
<com.google.android.material.button.MaterialButton
android:id="#+id/userDetails_btn_back"
style="#style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="88dp"
android:layout_height="50dp"
android:layout_marginTop="3dp"
android:backgroundTint="#color/black"
android:fontFamily="sans-serif"
android:text="BACK"
android:textSize="20sp"
app:cornerRadius="35dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/details_ti"
app:strokeColor="#color/primeOrng"
app:strokeWidth="1dp" />
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/details_ti"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:fontFamily="sans-serif-light"
android:hint="map.."
android:textColorHint="#color/white"
app:layout_constraintTop_toBottomOf="#+id/details_list_rv"
tools:layout_editor_absoluteX="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/listrow_question_et"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#drawable/custom_input"
android:drawablePadding="14dp"
android:fontFamily="sans-serif-light"
android:inputType="text"
android:maxLines="1"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:textColor="#color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/details_ti"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0"
tools:layout_editor_absoluteX="0dp" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
How can I solve this?
EDIT:
By replacing :
list.getChildCount();
with:
list.getAdapter().getItemCount()
I get the exact size (6) and now I understand it is related to the fact RecycleView recycles the views and not keeping them all, so it will always be a maximum of 3 items(in my example).
now, my question is still how could I achieve my target of saving the selected answers in the spinners by clicking finishBtn(I understand that iterating them is not an option because of the same thing, or maybe there is a way?)

Android RecyclerView Single Click selects multiple rows

Hello I am developing an app which uses recyclerview to show items to select categories. I have added textview and checkbox on recyclerview item. The problem is if I select one checkbox, it also selects multiple checkbox in the list. For example if I select 1st checkbox in the list it automatically selects every 10th checkbox in the list. Thanks
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="5dp"
android:background="#FFF"
app:cardUseCompatPadding="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/categoryName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="14dp"
android:text="Category"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="#+id/categoryCount"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/categoryCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginBottom="16dp"
android:text="Count"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<CheckBox
android:id="#+id/categoryCheck"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginTop="36dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="36dp"
android:buttonTint="#color/red"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Adapter.java
public class CategorySelector extends RecyclerView.Adapter<CategorySelector.ViewHolder> {
LayoutInflater inflater;
List<Category> categoryList;
List<String> selectedItems = new ArrayList<>();
public CategorySelector(Context ctx, List<Category> categoryList){
inflater = LayoutInflater.from(ctx);
this.categoryList = categoryList;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.category_select, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.categoryName.setText(categoryList.get(position).getCategoryName());
holder.categoryCount.setText(String.valueOf(categoryList.get(position).getCategoryCount()));
holder.categoryCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
selectedItems.add(categoryList.get(position).getCategoryName());
} else{
selectedItems.remove(categoryList.get(position).getCategoryName());
}
}
});
}
#Override
public int getItemCount() {
return categoryList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView categoryName;
TextView categoryCount;
CheckBox categoryCheck;
public ViewHolder(#NonNull View itemView) {
super(itemView);
categoryName = itemView.findViewById(R.id.categoryName);
categoryCount = itemView.findViewById(R.id.categoryCount);
categoryCheck = itemView.findViewById(R.id.categoryCheck);
}
}
public List<String> getSelectedItems(){
return selectedItems;
}
}
In your checkBox changeListener use instead of using position use :
holder.getAdapterPosition()
then set your checkBox select with your item :
holder.categoryCheck.setChecked(//set your boolean is selected before);

Android Studio Constraintlayout align to the right programatically

I'm making a chat app and I'm having some trouble with the layout of my messages. I want the messages send by the logged in user to be aligned to the right of the layout and the messages send by other group members to be aligned to the left.
This is my xml file:
<android.support.constraint.ConstraintLayout
android:id="#+id/container_message"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<ImageView
android:id="#+id/user_image"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="8dp"
android:src="#color/colorBlack"
app:layout_constraintBottom_toBottomOf="#+id/container_message_text"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="#+id/date_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:fontFamily="#font/rubik_light"
android:text="19 juni, 00:32"
android:textSize="10sp"
app:layout_constraintStart_toStartOf="#+id/container_message_text"
app:layout_constraintTop_toBottomOf="#+id/container_message_text" />
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/container_message_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:paddingStart="12dp"
android:paddingTop="12dp"
android:paddingEnd="12dp"
app:cardBackgroundColor="#color/colorTextWhite"
app:cardCornerRadius="16dp"
app:cardElevation="0dp"
app:layout_constraintStart_toStartOf="parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="12dp"
android:paddingTop="7dp"
android:paddingEnd="12dp"
android:paddingBottom="7dp">
<TextView
android:id="#+id/message_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="#font/rubik"
android:textSize="16sp"
android:maxWidth="240dp" />
</FrameLayout>
</android.support.v7.widget.CardView>
Picture of the current layout:
I need the purple messages to be aligned to the right, how can this be done programmatically?
You should better try chat layout using two different layouts for sender's message and yours message and if you are using recyclerview then the following adapter might help you.
public class MessageListAdapter extends RecyclerView.Adapter {
private static final int VIEW_TYPE_MESSAGE_SENT = 1;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;
private Context mContext;
private List<UserMessage> mMessageList;
public MessageListAdapter(Context context, List<UserMessage> messageList) {
mContext = context;
mMessageList = messageList;
}
#Override
public int getItemCount() {
return mMessageList.size();
}
// Determines the appropriate ViewType according to the sender of the message.
#Override
public int getItemViewType(int position) {
UserMessage message = (UserMessage) mMessageList.get(position);
if (message.getSender().getUserId().equals(currentUserId)) {
// If the current user is the sender of the message
return VIEW_TYPE_MESSAGE_SENT;
} else {
// If some other user sent the message
return VIEW_TYPE_MESSAGE_RECEIVED;
}
}
// Inflates the appropriate layout according to the ViewType
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == VIEW_TYPE_MESSAGE_SENT) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message_sent, parent, false);
return new SentMessageHolder(view);
} else if (viewType == VIEW_TYPE_MESSAGE_RECEIVED) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message_received, parent, false);
return new ReceivedMessageHolder(view);
}
return null;
}
// Passes the message object to a ViewHolder so that the contents can be bound to UI.
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
UserMessage message = (UserMessage) mMessageList.get(position);
switch (holder.getItemViewType()) {
case VIEW_TYPE_MESSAGE_SENT:
((SentMessageHolder) holder).bind(message);
break;
case VIEW_TYPE_MESSAGE_RECEIVED:
((ReceivedMessageHolder) holder).bind(message);
}
}
private class SentMessageHolder extends RecyclerView.ViewHolder {
SentMessageHolder(View itemView) {
super(itemView);
//bind views
}
void bind(UserMessage message) {
//set values
}
}
private class ReceivedMessageHolder extends RecyclerView.ViewHolder {
ReceivedMessageHolder(View itemView) {
super(itemView);
//bind views
}
void bind(UserMessage message) {
//set values
}
}
}

RecyclerView makes single Items go left instead of them staying on the right

I just started an new app (an easy chat app) on Android and Im kind of stuck in the recyclerView. I am switching between 2 XML files to display a message either on the left or on the right of the screen. The messages on the left work fine, but the messages which should be displayed on the right jump to the left when debugging the app. In the original XML they are connected to the right with constraints.
Here is the code of the xml file of the message on the right:
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textViewMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0"
tools:text="Hi, sub?" />
</android.support.constraint.ConstraintLayout>
And the code from the adapter
public class ChatAdapter extends RecyclerView.Adapter{
private final Context mContext;
private final static int showLeft = 1;
private final static int showRight = 0;
public ChatAdapter(#NonNull Context context) {
mContext = context;
}
#Override
public NumberViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layoutId;
switch(viewType){
case showLeft:
layoutId = R.layout.message_received;
Log.d("Inflation: ", "left");
break;
case showRight:
layoutId = R.layout.message_sent;
Log.d("Inflation: ", "right");
break;
default:
throw new IllegalArgumentException("Invalid view type, value of " + viewType);
}
View view = LayoutInflater.from(mContext).inflate(layoutId, parent, false);
view.setFocusable(true);
return new NumberViewHolder(view);
}
#Override
public void onBindViewHolder(NumberViewHolder holder, int position) {
holder.message.setText(DataHandling.ChatMessages.get(position));
}
#Override
public int getItemCount() {
return DataHandling.ChatMessages.size();
}
#Override
public int getItemViewType(int position) {
if(DataHandling.MessageState.get(position) == 1){
return showRight; //If the message was received
}else{
return showLeft;
}
}
public class NumberViewHolder extends RecyclerView.ViewHolder{
TextView message;
public NumberViewHolder(View itemView) {
super(itemView);
message = (TextView) itemView.findViewById(R.id.textViewMessage);
}
}
How can I make them stick to the right side of the screen?
try the below, I basically replaced the Constraint Layout with Relative Layout and given layout_alignParentRight to true. this should work.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textViewMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:textSize="16sp"
android:layout_alignParentRight="true"
tools:text="Hi, sub?" />
</RelativeLayout>

Twitter like conversation view using RecyclerView and RelativeLayout

I am trying to implement an Activity similar to Twitter's tweet page. When a tweet is a reply to another tweet, if you scroll up, you can see the original tweet being replied to, which is initially hidden above the screen. Here is the code I have:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="#layout/toolbar"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/in_reply_to"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:layout_marginRight="5dp"
android:layout_marginEnd="5dp"
>
<ImageView
android:id="#+id/user_image"
android:layout_width="65dp"
android:layout_height="65dp"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:scaleType="fitXY"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
/>
<TextView
android:id="#+id/real_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:textSize="18sp"
android:layout_toRightOf="#id/user_image"
android:layout_toEndOf="#id/user_image"
/>
<TextView
android:id="#+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="0dp"
android:layout_below="#id/real_name"
android:layout_toRightOf="#id/user_image"
android:layout_toEndOf="#id/user_image"
android:textSize="15sp"
/>
<TextView
android:id="#+id/tweet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_below="#id/user_image"
android:textSize="18sp"
/>
</RelativeLayout>
</LinearLayout>
Unfortunately, in this code only the original tweet shows up and the RecyclerView remains hidden for some reason. Could someone help me out how to position them in such a way that the RecyclerView is hidden above the screen and is visible only if you scroll up?
Decided to expand on my comment above with code. You can have multiple ViewHolders in one RecyclerView.Adapter, each can have different layouts (R.layout.original_tweet and R.layout.other_tweets here). getItemViewType() sets which viewholder to show. I didn't test or run the code so there might be a few bugs, but it should give you an idea at least.
public class MyAdapter
extends RecyclerView.Adapter {
private static final int ORIGINAL_TWEET = 0;
private static final int OTHER_TWEETS = 1;
private List<String> mTweets;
public MyAdapter(List<String> tweets) {
mTweets = tweets;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (ORIGINAL_TWEET == viewType) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.original_tweet, parent, false);
return new OriginalTweetViewHolder(view);
} else {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.other_tweets, parent, false);
return new OtherTweetsViewHolder(view);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof OriginalTweetViewHolder) {
// populate with tweet data
} else if (holder instanceof OtherTweetsViewHolder) {
// populate with tweet data
}
}
#Override
public int getItemCount() {
return mTweets.size();
}
#Override
public int getItemViewType(int position) {
if (position == mTweets.size() - 1) {
// At bottom position
return ORIGINAL_TWEET;
} else {
return OTHER_TWEETS;
}
}
}
public static class OriginalTweetViewHolder extends RecyclerView.ViewHolder {
// ViewHolder fields
public OriginalTweetViewHolder(View view) {
super(view);
}
}
public static class OtherTweetsViewHolder extends RecyclerView.ViewHolder {
// ViewHolder fields
public OtherTweetsViewHolder(View view) {
super(view);
}
}

Categories

Resources