I am trying to create my own custom firebase recycler adapter for a chat app. I want to inflate two views in the adapter, one for the sender and one for the receiver, but don't know how.
How shall I proceed with this?
To inflate different views in a RecyclerView, you need to implement this function in your adapter:
public int getItemViewType(int position);
This function is called before onCreateViewHolder and allows you to return an int depending on the type of the view you want to inflate. You can imagine using an enum to achieve this:
public enum TYPE {
SENDER,
RECEIVER
}
This way you will return an int depending on the type (with type.ordinal()).
Then you will get your type on the function onCreateViewHolder(ViewGroup parent, int viewType), you will be able to match you type again TYPE.values()[viewType]. This way you will return the inflated layout depending on the type.
Finally on onBindViewHolder(TimelineItemViewHolder holder, int position), you will be able either to:
Call getItemViewType(int position) to know how to cast and display your contents
Using instanceof be able to detect what is the type of the ViewHolder you are looking at
Use an abstract class, extending RecyclerView.ViewHolder shared by your two ViewHolder, allowing you to call a common function, like display(MyObject object)
private static final int RIGHT_MSG = 0;
private static final int LEFT_MSG = 1;
/*Viewholder for messages*/
public static class MessageViewHolder extends RecyclerView.ViewHolder {
public EmojiconTextView messageTextView;
public TextView messengerTextView;
public CircleImageView messengerImageView;
public ImageView sendimage;
public ImageView videoview;
public TextView messageTime;
public MessageViewHolder(View v) {
super(v);
messageTextView = (EmojiconTextView) itemView.findViewById(R.id.messageTextView);
messengerTextView = (TextView) itemView.findViewById(R.id.messengerTextView);
messengerImageView = (CircleImageView) itemView.findViewById(R.id.messengerImageView);
sendimage = (ImageView) itemView.findViewById(R.id.image);
videoview = (ImageView) itemView.findViewById(R.id.videoview);
messageTime = (TextView)itemView.findViewById(R.id.message_time);
}
/*Firebase recycler Adapter*/
mFirebaseAdapter = new FirebaseRecyclerAdapter < FriendlyMessage, MessageViewHolder > (
FriendlyMessage.class, R.layout.item_message, MessageViewHolder.class,
mFirebaseDatabaseReference.child(MESSAGES_CHILD)) {
#Override
protected void populateViewHolder(final MessageViewHolder viewHolder, final FriendlyMessage friendlyMessage, int position) {
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
viewHolder.messageTextView.setText(friendlyMessage.getText());
viewHolder.messengerTextView.setText(friendlyMessage.getName());
viewHolder.messageTime.setText(DateFormat.format("MMM d, yyyy hh:mm a", friendlyMessage.getMessageTime()));
if (friendlyMessage.getPhotoUrl() == null) {
viewHolder.messengerImageView.setImageDrawable(ContextCompat.getDrawable(Chat.this,
R.drawable.ic_account_circle_black_36dp));
} else {
Glide.with(Chat.this).load(friendlyMessage.getPhotoUrl()).into(viewHolder.messengerImageView);
}
//for show send image
if (friendlyMessage.getImageUrl() == null) {
viewHolder.sendimage.setVisibility(View.GONE);
} else {
viewHolder.sendimage.setVisibility(View.VISIBLE);
Glide.with(Chat.this).load(friendlyMessage.getImageUrl()).into(viewHolder.sendimage);
}
//to show the videoattach in videoview
if (friendlyMessage.getVideoUrl() == null) {
Glide.with(Chat.this).load("").placeholder(R.drawable.videoiconcrop).into(viewHolder.videoview);
//viewHolder.videoview.setVisibility(View.GONE);
} else {
viewHolder.videoview.setVisibility(View.VISIBLE);
}
}
#Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == RIGHT_MSG) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_viewholder2, parent, false);
return new MessageViewHolder(view);
} else {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_viewholder1, parent, false);
return new MessageViewHolder(view);
}
}
#Override
public int getItemViewType(int position) {
FriendlyMessage model = getItem(position);
if (model.getContactNumber().equals(UserDetails.contact)) {
return RIGHT_MSG;
} else {
return LEFT_MSG;
}
}
};
/*Xml for messages i try to provide you one side try to make another side by using id same as this layout*/
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:emojicon="http://schemas.android.com/apk/res-auto">
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:id="#+id/messengerImageView"
android:src="#drawable/ic_account_circle_black_36dp"/>
<FrameLayout
android:id="#+id/incoming_layout_bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_marginRight="60dp"
android:layout_alignParentLeft="true"
android:background="#drawable/balloon_incoming_normal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold|italic"
android:text="Receiver"
android:textSize="16dp"
android:layout_marginRight="50dp"
android:layout_marginBottom="10dp"
android:paddingBottom="12dp"
android:layout_marginLeft="6dp"
android:layout_above="#+id/messageTextView"
android:id="#+id/messengerTextView"
android:layout_weight="0"/>
<hani.momanii.supernova_emoji_library.Helper.EmojiconTextView
android:id="#+id/messageTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6dp"
android:layout_marginTop="18dp"
android:layout_marginBottom="10dp"
android:autoLink="web"
android:text="Rahul Agrawal is a good boy but he does not know what he wants."
style="#style/chat_text_message_style"
emojicon:emojiconSize="30sp"/>
<TextView
android:id="#+id/message_time"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingRight="5dp"
android:text="11:15 PM"
android:layout_marginLeft="6dp"
style="#style/chat_timings"
android:layout_gravity="bottom|right"/>
<ImageView
android:id="#+id/image"
android:layout_width="150dp"
android:layout_height="160dp"
android:src="#drawable/ic_account_circle_black_36dp"
android:contentDescription="send_photo"
android:visibility="gone"
android:layout_marginTop="23dp"
android:layout_marginBottom="18dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_gravity="center"
android:scaleType="fitXY"/>
<ImageView
android:layout_width="150dp"
android:layout_height="120dp"
android:id="#+id/videoview"
android:contentDescription="send_video"
android:src="#drawable/videoiconcrop"
android:layout_marginTop="20dp"
android:layout_marginBottom="18dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_gravity="center"
android:visibility="gone"
/>
</FrameLayout>
</LinearLayout>
may be this code help you out Happy Coding
Related
I have a recycler inside fragment in view pager.
The problem that it put likes on user accounts in UI randomly but in DB everything is fine.
In logs, I see that random is not influence on BD. So the bug is only in UI part. After the refresh of the list, it can appear again and after that disappear.
I would like to share code but I already don't have an I idea where the problem could be. It might be in adapter/refresh list listener / XML or any other places. Please let me know what part of the code you need and I will provide it. Maybe it is a bug of recycler as itself and I can't fix it.
Adapter class code:
public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.UserViewHolder>{
private List<FsUser> fsUserList = new ArrayList<>();
private OnItemClickListener.OnItemClickCallback onItemClickCallback;
private OnItemClickListener.OnItemClickCallback onChatClickCallback;
private OnItemClickListener.OnItemClickCallback onLikeClickCallback;
private Context context;
public SearchAdapter(OnItemClickListener.OnItemClickCallback onItemClickCallback,
OnItemClickListener.OnItemClickCallback onChatClickCallback,
OnItemClickListener.OnItemClickCallback onLikeClickCallback) {
this.onItemClickCallback = onItemClickCallback;
this.onChatClickCallback = onChatClickCallback;
this.onLikeClickCallback = onLikeClickCallback;
}
public void addUsers(List<FsUser> userList) {
fsUserList.addAll(userList);
notifyItemRangeInserted(fsUserList.size() - userList.size(), fsUserList.size());
}
public void clearData(){
fsUserList.clear();
notifyDataSetChanged();
}
#NonNull
#Override
public UserViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user, parent, false);
return new UserViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull UserViewHolder holder, int position) {
FsUser fsUser = fsUserList.get(position);
holder.bind(fsUser, position);
}
#Override
public int getItemCount() {
return fsUserList.size();
}
public String getLastItemId(){
return fsUserList.get(fsUserList.size() - 1).getUid();
}
class UserViewHolder extends RecyclerView.ViewHolder {
RelativeLayout container;
ImageView imageView, like, chat;
TextView name, country;
private LottieAnimationView animationView;
UserViewHolder(View itemView) {
super(itemView);
context = itemView.getContext();
container = itemView.findViewById(R.id.item_user_container);
imageView = itemView.findViewById(R.id.user_img);
like = itemView.findViewById(R.id.search_btn_like);
chat = itemView.findViewById(R.id.search_btn_chat);
name = itemView.findViewById(R.id.user_name);
country = itemView.findViewById(R.id.user_country);
animationView = itemView.findViewById(R.id.lottieAnimationView);
}
void bind(FsUser fsUser, int position){
ViewCompat.setTransitionName(imageView, fsUser.getName());
if (FirebaseUtils.isUserExist() && fsUser.getUid() != null) {
new FriendRepository().isLiked(fsUser.getUid(), flag -> {
if (flag) {
like.setBackground(ContextCompat.getDrawable(context, R.drawable.ic_favorite));
animationView.setVisibility(View.VISIBLE);
}
});
}
if(fsUser.getUid() != null) {
chat.setOnClickListener(new OnItemClickListener(position, onChatClickCallback));
like.setOnClickListener(new OnItemClickListener(position, onLikeClickCallback));
}
imageView.setOnClickListener(new OnItemClickListener(position, onItemClickCallback));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
if(fsUser.getImage().equals("default")){
Glide.with(context).load(context.getResources().getDrawable(R.drawable.default_avatar)).into(imageView);
} else {
Glide.with(context).load(fsUser.getImage()).thumbnail(0.5f).into(imageView);
}
name.setText(fsUser.getName());
country.setText(fsUser.getCountry());
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f).setDuration(500);
animator.addUpdateListener(valueAnimator ->
animationView.setProgress((Float) valueAnimator.getAnimatedValue()));
if (animationView.getProgress() == 0f) {
animator.start();
} else {
animationView.setProgress(0f);
}
}
}
}
And xml file of RecyclerView item:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/item_user_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="#dimen/user_cv_width"
android:layout_height="#dimen/user_cv_height"
android:layout_margin="#dimen/dp4"
android:elevation="#dimen/dp4">
<RelativeLayout
android:id="#+id/item_user_main_relative_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/item_user_top_relative_container"
android:layout_width="#dimen/user_rl_width"
android:layout_height="#dimen/user_rl_height">
<ImageView
android:id="#+id/user_img"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop"
android:src="#drawable/default_avatar" />
<RelativeLayout
android:id="#+id/item_user_top_relative"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/user_item_bg"
android:orientation="vertical">
<TextView
android:id="#+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/dp4"
android:textColor="#android:color/white"
android:textSize="#dimen/medium_text_size" />
<TextView
android:id="#+id/user_country"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:layout_marginStart="#dimen/dp4"
android:textSize="#dimen/medium_text_size" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
<RelativeLayout
android:id="#+id/item_user_bottom_relative_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/dp12">
<ImageView
android:id="#+id/search_btn_like"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/heart_outline"
android:contentDescription="#string/search_btn_like_desc"/>
<com.airbnb.lottie.LottieAnimationView
android:id="#+id/lottieAnimationView"
android:visibility="gone"
android:layout_width="#dimen/lottie_animation_view_size"
android:layout_height="#dimen/lottie_animation_view_size"
app:lottie_loop="true"
app:lottie_autoPlay="true"
app:lottie_fileName="like.json"/>
</RelativeLayout>
<ImageView
android:id="#+id/search_btn_chat"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="#dimen/dp12"
android:layout_weight="1"
android:src="#drawable/message_outline" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
Override this two methods inside your adapter
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
I made the FriendlyChat using firebase
However all the texts are appearing in same line, both from sender and receiver!
I want to apply chat bubbles with left and right alignment but have no idea where to start
I also want to wrap the text view inside chat bubble images? but i have no idea how to do that?
any help!
public class MessageAdapter extends ArrayAdapter<FriendlyMessage> {
public MessageAdapter(Context context, int resource, List<FriendlyMessage> objects) {
super(context, resource, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = ((Activity) getContext()).getLayoutInflater().inflate(R.layout.item_message, parent, false);
}
ImageView photoImageView = (ImageView) convertView.findViewById(R.id.photoImageView);
TextView messageTextView = (TextView) convertView.findViewById(R.id.messageTextView);
TextView authorTextView = (TextView) convertView.findViewById(R.id.nameTextView);
FriendlyMessage message = getItem(position);
boolean isPhoto = message.getPhotoUrl() != null;
if (isPhoto) {
messageTextView.setVisibility(View.GONE);
photoImageView.setVisibility(View.VISIBLE);
Glide.with(photoImageView.getContext())
.load(message.getPhotoUrl())
.into(photoImageView);
} else {
messageTextView.setVisibility(View.VISIBLE);
photoImageView.setVisibility(View.GONE);
messageTextView.setText(message.getText());
}
authorTextView.setText(message.getName());
return convertView;
}
}
item_message.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/lp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:orientation="vertical">
<ImageView
android:id="#+id/photoImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<TextView
android:id="#+id/messageTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="0"
android:background="#drawable/messenger_bubble_large_white"
android:padding="2dp"
android:textAppearance="?android:attr/textAppearanceLarge"
tools:text="Message" />
<TextView
android:id="#+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="Name" />
</LinearLayout>
Hi #Parjanya you have have to check type and based upon condition yo can hide one and show other
for me I used 2 different viewHolder and 2 different xml. My code is below;
MessageChatAdapter.java;
public class MessageChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<ChatMessage> mChatList;
public static final int SENDER = 0;
public static final int RECIPIENT = 1;
public MessageChatAdapter(List<ChatMessage> listOfFireChats) {
mChatList = listOfFireChats;
}
#Override
public int getItemViewType(int position) {
if (mChatList.get(position).getRecipientOrSenderStatus() == SENDER) {
return SENDER;
} else {
return RECIPIENT;
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
RecyclerView.ViewHolder viewHolder;
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
switch (viewType) {
case SENDER:
View viewSender = inflater.inflate(R.layout.layout_sender_message, viewGroup, false);
viewHolder = new ViewHolderSender(viewSender);
break;
case RECIPIENT:
View viewRecipient = inflater.inflate(R.layout.layout_recipient_message, viewGroup, false);
viewHolder = new ViewHolderRecipient(viewRecipient);
break;
default:
View viewSenderDefault = inflater.inflate(R.layout.layout_sender_message, viewGroup, false);
viewHolder = new ViewHolderSender(viewSenderDefault);
break;
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
switch (viewHolder.getItemViewType()) {
case SENDER:
ViewHolderSender viewHolderSender = (ViewHolderSender) viewHolder;
configureSenderView(viewHolderSender, position);
break;
case RECIPIENT:
ViewHolderRecipient viewHolderRecipient = (ViewHolderRecipient) viewHolder;
configureRecipientView(viewHolderRecipient, position);
break;
}
}
private void configureSenderView(ViewHolderSender viewHolderSender, int position) {
ChatMessage senderFireMessage = mChatList.get(position);
viewHolderSender.getSenderMessageTextView().setText(senderFireMessage.getMessage());
viewHolderSender.getmTimeStamp().setText(converteTimestamp(senderFireMessage.getTimestap()));
}
private void configureRecipientView(ViewHolderRecipient viewHolderRecipient, int position) {
ChatMessage recipientFireMessage = mChatList.get(position);
viewHolderRecipient.getRecipientMessageTextView().setText(recipientFireMessage.getMessage());
viewHolderRecipient.getmTimeStamp().setText(converteTimestamp(recipientFireMessage.getTimestap()));
}
/*==============ViewHolder===========*/
/*ViewHolder for Sender*/
public class ViewHolderSender extends RecyclerView.ViewHolder {
private TextView mSenderMessageTextView;
private TextView mTimeStamp;
public ViewHolderSender(View itemView) {
super(itemView);
mSenderMessageTextView = (TextView) itemView.findViewById(R.id.text_view_sender_message);
mTimeStamp = (TextView) itemView.findViewById(R.id.textView2);
}
public TextView getSenderMessageTextView() {
return mSenderMessageTextView;
}
public TextView getmTimeStamp() {
return mTimeStamp;
}
}
/*ViewHolder for Recipient*/
public class ViewHolderRecipient extends RecyclerView.ViewHolder {
private TextView mRecipientMessageTextView;
private TextView mTimeStamp;
public ViewHolderRecipient(View itemView) {
super(itemView);
mRecipientMessageTextView = (TextView) itemView.findViewById(R.id.text_view_recipient_message);
mTimeStamp = (TextView) itemView.findViewById(R.id.textView2);
}
public TextView getRecipientMessageTextView() {
return mRecipientMessageTextView;
}
public TextView getmTimeStamp() {
return mTimeStamp;
}
}
layout_sender_message.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text_view_sender_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="I am doing ok"
android:padding="8dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="2dp"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="#FFFFFF"
android:background="#drawable/sender_rounded_corners"
android:layout_alignParentRight="true" />
<TextView
android:id="#+id/textView2"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/text_view_sender_message"
android:layout_gravity="bottom"
android:layout_toLeftOf="#id/text_view_sender_message"
android:text="TextView"
android:textSize="12sp"
android:textStyle="italic"/>
</RelativeLayout>
layout_recipient_message.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text_view_recipient_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Hi. How are you?"
android:padding="8dp"
android:textStyle="bold"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="2dp"
android:textColor="#727272"
android:textSize="15sp"
android:background="#drawable/recipient_rounded_corners"/>
<TextView
android:id="#+id/textView2"
android:layout_width="69dp"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/text_view_recipient_message"
android:text="TextView"
android:textSize="12sp"
android:layout_gravity="bottom"
android:textStyle="italic"/>
</LinearLayout>
Pretty basic and needs to be fixed but this will give you a headstart.
I think you should use two different custom components for chat left and right bubbles.
Set as a background of TextView and make the boolean condition for show and hide two chat bubbles.
If you want more information and demo with use of firebase then please check below link:
https://www.androidtutorialpoint.com/firebase/real-time-android-chat-application-using-firebase-tutorial/
I hope it helps you.
Thank you:)
Just two words Answer...
Use Gravity
eg
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) _chat_view.getLayoutParams();
lp.gravity = Gravity.END | Gravity.RIGHT;
_chat_view.setLayoutParams(lp);
where _chat_view is your Message (LinearLayout) container.
Based on my previous question , I have a problem with onClick on CardView in my RecyclerView. I need to change the card layout when the CardView is clicked with another card layout xml. I follow this and this this but its not work. I dont too understand how to declare one CardView layout again in my code. Here my Code :
Adapter.Java
public class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final int view1 = 0;
public static final int view2 = 1;
private static OnRecyclerViewItemClickedListener recyclerViewItemClickedListener;
public void setOnRecyclerViewClickedListener (OnRecyclerViewItemClickedListener l) {
recyclerViewItemClickedListener = l;
}
public interface OnRecyclerViewItemClickedListener {
void OnRecyclerViewItemClicked(int position);
void OnRecyclerViewItemBind(ViewHolder holder, int position);
int OnRecyclerViewItemCount();
}
public Adapter() {
super();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView;
if (viewType == view1) {
itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.table_item_empty, parent, false);
return new ViewHolder(itemView);
}
else if (viewType == view2) {
itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.table_item_occupied, parent, false);
return new ViewHolder2(itemView);
}
return null;
}
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
recyclerViewItemClickedListener.OnRecyclerViewItemBind((ViewHolder) holder, position);
}
#Override
public int getItemCount() {
return recyclerViewItemClickedListener.OnRecyclerViewItemCount();
}
public int getItemViewType() { return recyclerViewItemClickedListener.getItemViewType(); }
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView txt_no_table;
public TextView txt_no_table_occ;
public TextView txt_pax_occ;
public TextView txt_guest_name_occ;
public TextView txt_bill_occ;
public Chronometer txt_time_occ;
public CardView cardview_table;
public LinearLayout title_layout;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
txt_no_table = (TextView) itemView.findViewById(R.id.txt_no_table_empty);
txt_no_table_occ = (TextView) itemView.findViewById(R.id.txt_no_table);
txt_pax_occ = (TextView) itemView.findViewById(R.id.txt_pax);
txt_guest_name_occ = (TextView)itemView.findViewById(R.id.txt_guestname);
txt_bill_occ = (TextView) itemView.findViewById(R.id.txt_bill);
txt_time_occ = (Chronometer) itemView.findViewById(R.id.txt_time);
cardview_table = (CardView) itemView.findViewById(R.id.table_card_empty);
title_layout = (LinearLayout) itemView.findViewById(R.id.table_ll1);
}
#Override
public void onClick(View itemView) {
recyclerViewItemClickedListener.OnRecyclerViewItemClicked(getAdapterPosition());
}
}
public class ViewHolder2 extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView txt_no_table2;
public TextView txt_pax2;
public TextView txt_guest_name2;
public TextView txt_bill2;
public TextView txt_time2;
public ViewHolder2 (View itemView) {
super(itemView);
itemView.setOnClickListener(this);
txt_no_table2 = (TextView) itemView.findViewById(R.id.txt_no_table_);
txt_pax2 = (TextView) itemView.findViewById(R.id.txt_pax_);
txt_guest_name2 = (TextView)itemView.findViewById(R.id.txt_guestname_);
txt_bill2 = (TextView) itemView.findViewById(R.id.txt_bill_);
txt_time2 = (TextView) itemView.findViewById(R.id.txt_time_);
}
#Override
public void onClick(View itemView) {
recyclerViewItemClickedListener.OnRecyclerViewItemClicked(getAdapterPosition());
}
}
}
Here My Activity :
adapter.setOnRecyclerViewClickedListener(new Adapter.OnRecyclerViewItemClickedListener() {
#Override
public void OnRecyclerViewItemClicked(int position) {
try {
JSONObject currTable = filteredTableList.getJSONObject(position);
if (currTable.has("selected")) {
currTable.put("selected", !currTable.getBoolean("selected"));
} else {
currTable.put("selected",true);
}
adapter.notifyItemChanged(position);
} catch (JSONException e) {
e.printStackTrace();
}
try
{
Toast.makeText(TableActivity.this, filteredTableList.getJSONObject(position).getString("tischnr"), Toast.LENGTH_SHORT).show();
}
catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void OnRecyclerViewItemBind(Adapter.ViewHolder holder, int position) {
try {
JSONObject currTable = filteredTableList.getJSONObject(position);
holder.txt_no_table.setText(currTable.getString("tischnr"));
holder.txt_guest_name_occ.setText("");
holder.txt_pax_occ.setText("");
holder.txt_bill_occ.setText("");
int queasy33Index = ProgramMethod.getJSONArrayIndex(queasy33List,"number2", currTable.getInt("tischnr"));
if (queasy33Index >= 0) {
holder.txt_guest_name_occ.setText(queasy33List.getJSONObject(queasy33Index).getString("char2"));
holder.txt_pax_occ.setText(queasy33List.getJSONObject(queasy33Index).getString("number3"));
}
if (currTable.has("selected") && currTable.getBoolean("selected")) {
holder.itemView.setBackgroundResource(R.color.colorRedTableOcc);
holder.txt_no_table.setVisibility(View.INVISIBLE);
holder.txt_no_table_occ.setVisibility(View.VISIBLE);
holder.txt_bill_occ.setVisibility(View.VISIBLE);
holder.txt_pax_occ.setVisibility(View.VISIBLE);
holder.txt_time_occ.setVisibility(View.VISIBLE);
holder.txt_guest_name_occ.setVisibility(View.VISIBLE);
} else {
holder.itemView.setBackgroundResource(R.color.colorTableGreen);
holder.txt_no_table.setVisibility(View.VISIBLE);
holder.txt_no_table_occ.setVisibility(View.INVISIBLE);
holder.txt_bill_occ.setVisibility(View.INVISIBLE);
holder.txt_pax_occ.setVisibility(View.INVISIBLE);
holder.txt_time_occ.setVisibility(View.INVISIBLE);
holder.txt_guest_name_occ.setVisibility(View.INVISIBLE);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public int OnRecyclerViewItemCount() {
return filteredTableList.length();
}
});
My table_item_empty.xml (first layout) :
<?xml version="1.0" encoding="utf-8"?>
<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/table_card_empty"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#color/colorTableGreen"
app:cardCornerRadius="15dp"
app:cardElevation="5dp"
android:layout_margin="3dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="2dp"
android:gravity="center">
<RelativeLayout
android:id="#+id/table_rl1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/table_ll1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
<TextView
android:id="#+id/txt_no_table"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textSize="15dp"
android:gravity="center"
android:textColor="#color/colorWhite"
android:visibility="invisible"/>
</LinearLayout>
<TextView
android:id="#+id/txt_pax"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="1dp"
android:text="5"
android:textSize="10dp"
android:textColor="#color/colorWhite"
android:drawableLeft="#drawable/ic_airline_seat_recline_normal_white_18dp"
android:visibility="invisible"/>
<TextView
android:id="#+id/txt_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="10:00"
android:textSize="10dp"
android:textColor="#color/colorWhite"
android:drawableLeft="#drawable/ic_access_time_white_18dp"
android:layout_alignParentTop="true"
android:layout_toEndOf="#+id/txt_pax"
android:layout_marginStart="2dp"
android:visibility="invisible"/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/table_rl2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/table_rl1">
<TextView
android:id="#+id/txt_guestname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="1dp"
android:text="Budi"
android:textSize="10dp"
android:textColor="#color/colorWhite"
android:drawableLeft="#drawable/ic_supervisor_account_white_18dp"
android:visibility="invisible"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/table_rl2">
<TextView
android:id="#+id/txt_bill"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="10000"
android:drawableLeft="#drawable/ic_attach_money_white_18dp"
android:textSize="10dp"
android:textColor="#color/colorWhite"
android:layout_marginStart="1dp"
android:visibility="invisible"/>
</RelativeLayout>
<TextView
android:id="#+id/txt_no_table_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="12"
android:textSize="25dp"
android:gravity="center_vertical|center_horizontal"
android:textColor="#color/colorWhite"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
</android.support.v7.widget.CardView>
App looks like :
My code make a first layout gone when i clicked but i want to show/change another card layout.
This is CardView1 Looks like :
Another CardView xml (CardView2) :
EDITED :
I trick it. Now when one or more item clicked, it will change the view into like this :
But i still want to try with two different layout.xml view when item clicked. Its work because i only 'play' with 'INVISIBLE' and 'VISIBLE' in element on one layout, not the xml.
[EDITED] :
I'm still try to make my RecyclerView with two Layout view. I improve my Adapter like above. I follow this but i get a litle problem. In my Acivity, i call my itemView from ViewHolder1 with holder (example: holder.txt_time....) like my code above. I want to know how i can call my second holder (ViewHolder2) in my Activity? I try to make hard code with add some listener but its not work for me :(
Maybe somebody can help and guide me to fix my code. Every answer will helpful for me. Thanks before.
I'm using a CardView Layout in a RecyclerView, JSON will load data and fill the adapter. My layout includes a ImageView, a TextView and everything is fine.
This is the Adapter class (UPDATED):
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private static final int TYPE_HEADER = 4;
private static final int TYPE_ITEM = 1;
Context context;
List<CarData> getCarData; // getDataAdapter
ImageLoader imageThumbLoader;
public RecyclerViewAdapter(List<CarData> getCarData, Context context){
super();
this.getCarData = getCarData;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_items, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder Viewholder, int position) {
// if (!isPositionHeader(position)) {
CarData getCarData1 = getCarData.get(position - 1);
imageThumbLoader = ServerImageParseAdapter.getInstance(context).getImageLoader();
imageThumbLoader.get(getCarData1.getImageThumb(),
ImageLoader.getImageListener(
Viewholder.imageThumb,//Server Image
R.mipmap.ic_launcher,//Before loading server image the default showing image.
android.R.drawable.ic_dialog_alert //Error image if requested image dose not found on server.
)
);
Viewholder.imageThumb.setImageUrl(getCarData1.getImageThumb(), imageThumbLoader);
Viewholder.titleName.setText(getCarData1.getTitleName());
Viewholder.doorName.setText(Html.fromHtml("<b>Số cửa:</b> " + getCarData1.getDoorName()));
Viewholder.seatName.setText(Html.fromHtml("<b>Số ghế:</b> " + getCarData1.getSeatName()));
Viewholder.cityName.setText(Html.fromHtml(getCarData1.getCityName()));
Viewholder.districtName.setText(Html.fromHtml(getCarData1.getDistrictName()));
// }
}
public int getDataAdapter() {
return getCarData == null ? 0 : getCarData.size();
}
#Override
public int getItemViewType(int position) {
if (isPositionHeader(position)) {
return TYPE_HEADER;
}
return TYPE_ITEM;
}
#Override
public int getItemCount() {
return getDataAdapter(); // + 1
}
private boolean isPositionHeader(int position) {
return position == 0;
}
class ViewHolder extends RecyclerView.ViewHolder{
public TextView titleName;
public NetworkImageView imageThumb;
public TextView doorName;
public TextView seatName;
public TextView cityName;
public TextView districtName;
public ViewHolder(View itemView) {
super(itemView);
titleName = (TextView) itemView.findViewById(R.id.titleName);
imageThumb = (NetworkImageView) itemView.findViewById(R.id.imageThumb);
doorName = (TextView) itemView.findViewById(R.id.doorName);
seatName = (TextView) itemView.findViewById(R.id.seatName);
cityName = (TextView) itemView.findViewById(R.id.cityName);
districtName = (TextView) itemView.findViewById(R.id.districtName);
}
}
}
My layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cardview1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardElevation="3dp"
card_view:contentPadding="3dp"
card_view:cardCornerRadius="3dp"
card_view:cardMaxElevation="3dp"
card_view:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.android.volley.toolbox.NetworkImageView
android:id="#+id/imageThumb"
android:layout_width="400dp"
android:layout_height="230dp"
android:src="#mipmap/ic_launcher"
android:gravity="top"
android:scaleType="centerCrop"/>
<TextView
android:id="#+id/titleName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Image View"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/imageThumb"
android:layout_toEndOf="#+id/imageThumb"
android:layout_marginLeft="20dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<TextView
android:id="#+id/doorName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"/>
<TextView
android:id="#+id/seatName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<TextView
android:id="#+id/cityName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"/>
<TextView
android:id="#+id/districtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"/>
</LinearLayout>
<TextView
android:id="#+id/checkStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="KIỂM TRA TÌNH TRẠNG XE"
android:textColor="#color/color_primary_green_dark"
android:textStyle="bold"
android:textSize="12dp"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/textView_item32"
android:layout_toEndOf="#+id/textView_item32"
android:layout_marginLeft="20dp"/>
</LinearLayout>
But when I load data for the first time, there is a redundant item. Look at the following attachment:
The exception has happened when updated code:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: pl.michalz.hideonscrollexample, PID: 9794
java.lang.ArrayIndexOutOfBoundsException: length=18; index=-1
at java.util.ArrayList.get(ArrayList.java:310)
at pl.michalz.hideonscrollexample.RecyclerViewAdapter$override.onBindViewHolder(RecyclerViewAdapter.java:54)
at pl.michalz.hideonscrollexample.RecyclerViewAdapter$override.access$dispatch(RecyclerViewAdapter.java)
at pl.michalz.hideonscrollexample.RecyclerViewAdapter.onBindViewHolder(RecyclerViewAdapter.java:0)
at pl.michalz.hideonscrollexample.RecyclerViewAdapter.onBindViewHolder(RecyclerViewAdapter.java:20)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5768)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5801)
How do I remove this redundant item in the CardView?
You have + 1 in your overridden getItemCount() method. It causes that you have one extra item in your list.
Then you have the method isPositionHeader, which you call in the onBindViewHolder method to find out, if the position is a header position. You are filling your cardview with data, if it is not the header position. But if it is the header position, you just skip it. So the first item, which is blank, is the header using the same cardview, as the other items, in fact.
Try to remove the + 1 and this condition if (!isPositionHeader(position)).
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);
}
}