I have a fragment in my Activity with the below structure:
<android.support.v7.widget.RecyclerView android:id="#+id/cafeRecyclerView"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
it has only a RecyclerView. and it has an Adapter with the below code:
public class InfinityFragmentRecyclerAdapter extends RecyclerView.Adapter implements HasDatabase
{
protected JsonDatabase jsonDatabase = new JsonDatabase();
protected Context mContext;
protected int arrangeMode;
public InfinityFragmentRecyclerAdapter(Context context, int viewMode)
{
mContext = context;
arrangeMode = viewMode;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i)
{
View view;
if (arrangeMode == SupportsGridAndListArrangement.GRID_VIEW)
{
view = LayoutInflater.from(viewGroup.getContext()).inflate
(R.layout.grid_advertisement_layout, null);
}
else
{
view = LayoutInflater.from(viewGroup.getContext()).inflate
(R.layout.list_advertisement_layout, null);
}
return new ItemHolder(view, mContext, arrangeMode);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i)
{
AdItemPassiveDataSet adItemPassiveDataSet = (AdItemPassiveDataSet) jsonDatabase.getDataSetAt(i);
Picasso.with(mContext).load(adItemPassiveDataSet.getItemThumbnailAddress()).into
(((ItemHolder) viewHolder).imageView);
((ItemHolder) viewHolder).adID = adItemPassiveDataSet.getItemID();
((ItemHolder) viewHolder).userID = adItemPassiveDataSet.getUserID();
((ItemHolder) viewHolder).userRole = adItemPassiveDataSet.getUserRole();
((ItemHolder) viewHolder).price.setText(adItemPassiveDataSet.getItemPrice(), false);
((ItemHolder) viewHolder).title.setText(adItemPassiveDataSet.getItemTitle(), false);
((ItemHolder) viewHolder).state.setText(adItemPassiveDataSet.getItemState(), false);
((ItemHolder) viewHolder).date.setText(adItemPassiveDataSet.getItemTime(), false);
if (arrangeMode == SupportsGridAndListArrangement.LIST_VIEW)
{
((ItemHolder) viewHolder).description.setText(adItemPassiveDataSet.getItemDescription());
StaggeredGridLayoutManager.LayoutParams layoutParams =
new StaggeredGridLayoutManager.LayoutParams
(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setFullSpan(true);
viewHolder.itemView.setLayoutParams(layoutParams);
}
}
#Override
public int getItemCount()
{
if (jsonDatabase != null)
{
return jsonDatabase.getCount();
}
else
{
return 0;
}
}
#Override
public JsonDatabase getDatabase()
{
return jsonDatabase;
}
public void append(Object newJsonDatabase)
{
int currentCount = 0;
if (jsonDatabase != null)
{
currentCount = jsonDatabase.getCount();
}
int newCount = ((JsonDatabase) newJsonDatabase).getCount();
jsonDatabase.appendAtEnd((JsonDatabase) newJsonDatabase);
for (int i = currentCount; i < (currentCount + newCount); i++)
{
notifyItemInserted(i);
}
}
}
I also setup my fragment at this way:
recyclerView = (RecyclerView) findViewById(R.id.cafeRecyclerView);
recyclerViewAdapter = new InfinityFragmentRecyclerAdapter(this, SupportsGridAndListArrangement.GRID_VIEW);
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
recyclerView.setAdapter(recyclerViewAdapter);
and each time I receive new data from server, I add them to RecyclerView in CardViews at this way:
recyclerViewAdapter.append(newJsonDatabase);
every thing is fine! I can download data, add them to recycler view and so on but the problem is that the recycler view doesnt scroll fluently. when the top or bottom of my cardviews in recycler view reach to the top of recycler view, it somehow sticks and jumps some pixels! I'm really confused. any idea please? any help will be appreciated.
try to use notifyItemRangeInserted() instead of notifyItemInserted()
if I understand correctly your code should be like this
notifyItemInserted(currentCount, currentCount + newCount);
Related
I am using nestedRecyclerView with Vertical parent recyclerview and horizontal child views. I have list of 10 items and each item contains a list for child recyclerview.
When I run the app, parent adapter's onbindviewholder getting called 10 items which is the total size of the parent list. I want to know why it is happening. It should call 4 or 5 onbindviewholder depending on the screen size but it is calling for all items which is unintended.
Parent Recyclerview initialization
homeRecyclerViewAdapter = new HomeRecyclerViewAdapter(getContext(), MR, (AppCompatActivity) getActivity());
homeRecyclerViewAdapter.setDataList(homeArrayList);
LinearLayoutManager mLinearLayoutManager3 = new LinearLayoutManager(getContext());
mLinearLayoutManager3.setOrientation(CustomLinearLayoutManager.VERTICAL);
homeRecyclerView.setLayoutManager(mLinearLayoutManager3);
homeRecyclerView.setAdapter(homeRecyclerViewAdapter);
Parent Adapter -
public class HomeRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List dataList;
private Context mContext;
Typeface MR;
static String PACKAGE_NAME;
Utils utils;
CustomClickEvents customClickEvents;
AppCompatActivity appCompatActivity;
public HomeRecyclerViewAdapter(Context mContext, Typeface MR, int type, CustomClickEvents customClickEvents) {
this.mContext = mContext;
this.MR = MR;
this.customClickEvents = customClickEvents;
utils = new Utils();
}
RecyclerView.RecycledViewPool pool;
public HomeRecyclerViewAdapter(Context mContext, Typeface MR, AppCompatActivity appCompatActivity) {
pool = new RecyclerView.RecycledViewPool();
this.mContext = mContext;
this.MR = MR;
this.appCompatActivity = appCompatActivity;
utils = new Utils();
}
public void setDataList(List upiAppsList) {
this.dataList = upiAppsList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
PACKAGE_NAME = mContext.getPackageName();
if (viewType == Constants.HomePageViewTypes.TYPE_0) {
view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_layout, null);
return new RecyclerViewHolder(view);
} else if (viewType == Constants.HomePageViewTypes.TYPE_1) {
view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_layout, null);
return new RecyclerViewHolder(view);
} else if (viewType == Constants.HomePageViewTypes.TYPE_2) {
view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_layout, null);
return new RecyclerViewHolder(view);
}
return null;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder itemViewHolder, int position) {
Log.d("recyclerview", "HomeRecyclerViewHolder onbindviewholder + pos" + position);
Log.d("recyclerview", "HomeRecyclerViewHolder dataList.get(position):" + dataList.get(position));
RecyclerViewHolder holder = (RecyclerViewHolder) itemViewHolder;
holder.commonRecyclerViewAdapter.setDataList(((HomePageViewModel) dataList.get(position)).getDataList());
}
public void setbackgroundcolortoitem(int position, RecyclerViewHolder viewHolder, boolean is_checked) {
int modulus_position = position % 4;
Log.d("tag", "position ---- > " + modulus_position);
}
class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
RecyclerView mRecyclerView;
CommonRecyclerViewAdapter commonRecyclerViewAdapter;
public RecyclerViewHolder(View itemView) {
super(itemView);
mRecyclerView = itemView.findViewById(R.id.mrecyclerview);
mRecyclerView.setPadding((int) (8 * utils.getScreenDensity(mContext)), 0, 0, (int) (8 * utils.getScreenDensity(mContext)));
// mRecyclerView.requestDisallowInterceptTouchEvent(false);
commonRecyclerViewAdapter = new CommonRecyclerViewAdapter(mContext, MR, 6, appCompatActivity);
LinearLayoutManager mLinearLayoutManager3 = new LinearLayoutManager(appCompatActivity, LinearLayoutManager.HORIZONTAL, false) {
#Override
public boolean checkLayoutParams(RecyclerView.LayoutParams lp) {
// force height of viewHolder here, this will override layout_height from xml
Log.d("upisdk", "HomeRecyclerView getwidth:" + getWidth());
lp.width = (int) (getWidth() / 1.6);
return true;
}
};
mLinearLayoutManager3.setOrientation(CustomLinearLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(mLinearLayoutManager3);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setAdapter(commonRecyclerViewAdapter);
}
#Override
public void onClick(View v) {
int position = getLayoutPosition();
switch (v.getId()) {
case R.id.mainlayout:
break;
}
}
}
#Override
public int getItemCount() {
return dataList.size();
}
#Override
public int getItemViewType(int position) {
if (dataList.get(position) instanceof HomePageViewModel) {
if (((HomePageViewModel) dataList.get(position)).getLayoutType() == Constants.HomePageViewTypes.TYPE_0) {
return Constants.HomePageViewTypes.TYPE_0;
}
}
return -1;
}
}
I want parent onbindviewholder to get called for the items displaying currently on screen which is the supposed behaviour of RecyclerView.
Is the parent View of the Parent RecycleView a ScrollView or NestedScrollView, bro? If true, please remove it
I am using recyclerview to show all my message in my app. But it always showing the messages in the left side of the chat room.
How can I achieve this?
This is my code:
Here my adapter always goes to the else part and listing all the message in the left side of the screen(i.e) other user messages
Sample image
Adapter:
public class ChatMessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Messages> msgDtoList;
private final List<Messages> mData;
public static final int VIEW_TYPE_SENDER = 1;
public static final int VIEW_TYPE_RECEIVER = 2;
public ChatMessageAdapter(List<Messages> msgDtoList) {
this.msgDtoList = msgDtoList;
mData = msgDtoList;
}
public void setData(#Nullable Messages[] data) {
msgDtoList.clear();
for (Messages model : data) {
if (model instanceof Messages) {
mData.add(model);
continue;
}
}
#Override
public int getItemViewType(int position) {
Messages msgDto = this.msgDtoList.get(position);
if (msgDto.getmSender().getId() == Profile.getInstance().getId()) {
return VIEW_TYPE_SENDER;
}
else {
return VIEW_TYPE_RECEIVER;
}
}
#Override
public int getItemCount() {
return msgDtoList.size();
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
View v;
if(mMessages.getmSender().getId() == Profile.getInstance().getId()) {
sentViewHolder(holder, position);
} else if (msgDto.getmSender().getId() != Profile.getInstance().getId()) {
receivedViewHolder(holder, position);
}
}
#SuppressLint("ResourceAsColor")
private void sentViewHolder(RecyclerView.ViewHolder holder, int position) {
Messages msgDto = this.msgDtoList.get(position);
((SenderMessageHolder)holder).rightMsgTextView.setText(msgDto.getmMSg());
((SenderMessageHolder)holder).mDateTimestamp.setText(msgDto.getmTimestamp());
((SenderMessageHolder)holder).rightMsgTextView.setTextColor(R.color.yellow);
((SenderMessageHolder)holder).rightMsgTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
}
#SuppressLint("ResourceAsColor")
private void receivedViewHolder(RecyclerView.ViewHolder holder, int position) {
Messages msgDto = this.msgDtoList.get(position);
((ReceiverMessageHolder)holder).leftMsgTextView.setText(msgDto.getmMSg());
((ReceiverMessageHolder)holder).mDateTimestamp.setText(msgDto.getmTimestamp());
((ReceiverMessageHolder)holder).leftMsgTextView.setTextColor(R.color.red);
((ReceiverMessageHolder)holder).leftMsgTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Messages msgDto = this.msgDtoList.get(viewType);
if (msgDto.getmSender().getId() == Profile.getInstance().getId() ) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.sender_message_layout, parent, false);
return new SenderMessageHolder(view);
} else {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.receiver_message_layout, parent, false);
return new ReceiverMessageHolder(view);
}
}
}
}
In ChatFragment.java
#Override
public void onViewCreated(View v, #Nullable Bundle b) {
super.onViewCreated(v, b);
mChat = (TextView) v.findViewById(R.id.chat_messages);
mSendMsgInputBox = (EditText) v.findViewById(R.id.chat_input_msg);
mSendMsg = (ImageView) v.findViewById(R.id.chat_send_msg);
mChatMessageRecyclerView = (RecyclerView) v.findViewById(R.id.recycler_view);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
linearLayoutManager.setStackFromEnd(true);
linearLayoutManager.setSmoothScrollbarEnabled(true);
mChatMessageRecyclerView.setLayoutManager(linearLayoutManager);
final List<Messages> msgDtoList = new ArrayList<LastMessageContent>();
int newMsgPosition = msgDtoList.size() - 1;
mChatMessageRecyclerView.scrollToPosition(0);
mChatMessageRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
mChatMessageRecyclerView.setHasFixedSize(true);
mChatMessageRecyclerView.setAdapter(mAdapter);
ArrayList<Messages> messagesList = new ArrayList<>();
for (int i=0;i<10;i++) {
// messagesList.add(new LastMessageContent( mSendMsgInputBox.getText().toString(), Profile.getInstance().getId() == mChatMessage.getmSender().getId() ? ChatMessageAdapter.VIEW_TYPE_SENDER : ChatMessageAdapter.VIEW_TYPE_RECEIVER));
}
List<List<Messages>> itemList = new ArrayList<>();
mSendMsg.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String msgContent = mSendMsgInputBox.getText().toString();
if(!TextUtils.isEmpty(msgContent))
{
Messages msgDto = mChatMessage.getmessages();
msgDtoList.add(msgDto);
itemList.add(msgDtoList);
mAdapter.notifyDataSetChanged();
if (mSendMsgInputBox.toString() != "") {
LastMessageContent msgDto1 = new LastMessageContent(mChatMessage.getmLastMessageContent().getmMSg(), mChatMessage.getId());
System.out.println("msgDto1msgDto1 ==" + msgDto1);
msgDtoList.add(msgDto1);
}
mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int messageCount = mAdapter.getItemCount();
int lastVisiblePosition =
linearLayoutManager.findLastCompletelyVisibleItemPosition();
// If the recycler view is initially being loaded or the
// user is at the bottom of the list, scroll to the bottom
// of the list to show the newly added message.
if (lastVisiblePosition == -1 ||
(positionStart >= (friendlyMessageCount - 1) &&
lastVisiblePosition == (positionStart - 1))) {
mChatMessageRecyclerView.scrollToPosition(positionStart);
}
}
});
}
}
you are checking your viewType twice. you should not check it again in onCreateViewHolder.
try something like this:
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_SENDER) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.sender_message_layout, parent, false);
return new SenderMessageHolder(view);
} else {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.receiver_message_layout, parent, false);
return new ReceiverMessageHolder(view);
}
}
I'm trying to build a simple activity for messaging in android.
I have a RecyclerView that list the messages and I set a ScrollListener on it.
When the firstVisibleItem is the third of the list (RecyclerView stack from end), I will make a call to load other elements.
I add this element to my array and I set a new adapter on my RecyclerView for the update.
When I set the new adapter, the list starts one more time from the last message.
So far I have tried to use scrollToPosition to go to the message where the user was before scrollListener was triggered, but still not work at all because the lastVisibleItem become 1 every time.
Is there a way to maintain the last firstVisible element and set this element as the top element after reset the Adapter?
This is the onCreateMethod.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat);
lastOffset = 0;
requestSize = 20;
loadMessage()
mAdapter = new ChatAdapter(this,mess);
llm = new LinearLayoutManager(this);
llm.setStackFromEnd(true);
mex_list.setLayoutManager(llm);
mex_list.setAdapter(mAdapter);
mex_list.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int lastVisible = llm.findLastVisibleItemPosition();
int firstVisible = llm.findFirstVisibleItemPosition();
lastFirstVisibleItem = firstVisibleItem; //lastFirstVisibleItem is a global variable
if(firstVisible <= 3){
if(!loading) {
loading = true;
loadMessage();
}
}
Log.d("Test Scroll", "LAST: "+ lastVisible+" FIRST: "+firstVisible);
}
});}
This is where the laodMessage() result was managed.
public void manageResult(Object pr, int caller) {
if(caller == MESSAGES_REQ){
if(mess == null)
mess = new ArrayList<>();
ArrayList<Message> tail = (ArrayList<Message>) pr;
if(tail != null && tail.size() > 0) {
lastOffset += tail.size();
mess.addAll(tail);
mAdapter = new ChatAdapter(ctx, mess);
mex_list.setAdapter(mAdapter);
}
llm.scrollToPosition(lastFirstVisibleItem);//lastFirstVisibleItem became always 1
spinner.setVisibility(View.GONE);
printEmpMex(View.GONE);
mex_list.setVisibility(View.VISIBLE);
loading = false;
}
}
This is the ChatAdapter.
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ViewHolder> {
private ArrayList<Message> listOfMessages;
private static Context ctx;
private static final int SENT = 100;
private static final int RECIVED = 200;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView text;
public TextView hour;
public ViewHolder(View v) {
super(v);
text = (TextView) v.findViewById(R.id.text_body);
hour = (TextView) v.findViewById(R.id.time);
}
void bind(Message m){
text.setText(m.getBody());
hour.setText(formatDateAndHour(m.getDate()));
}
}
public ChatAdapter(Context ctx, ArrayList<Message> m) {
listOfMessages = m;
this.ctx = ctx;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view;
if (viewType == SENT) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.single_mex_sent, parent, false);
return new ViewHolder(view);
}
else if (viewType == RECIVED){
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.single_mex_recived, parent, false);
return new ViewHolder(view);
}
return null;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Message mex = listOfMessages.get(position);
holder.bind(mex);
}
#Override
public int getItemCount() {
return listOfMessages.size();
}
#Override
public int getItemViewType(int position) {
Message m = listOfMessages.get(position);
if(m.getSender().getIdUser().equals(loggedUser.getIdUser()))
return SENT;
else
return RECIVED;
}}
I really don't know how to make it work.
Every approach is welcome.
Thanks in advance.
Hey community I want to make a RecyclerView like in the chat applications.
I tried setStackFromEnd and it's working good.
final LinearLayoutManager llm = new LinearLayoutManager(getApplicationContext());
llm.setOrientation(LinearLayoutManager.VERTICAL);
llm.setStackFromEnd(true);
My on load more code based on this tutorial, At the end of tutorial you should see a video : Recyclerview Bottom Progress
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
if (mOnLoadMoreListener != null) {
mOnLoadMoreListener.onLoadMore();
}
isLoading = true;
}
}
});
So I need to make a RecyclerView like in chat applications. Stack from end is working perfect but I need to trigger load more method when I go top instead of going bottom. Also add new items on top instead of bottom. Thanks in advance.
You don't need to make use of onScrollListener, if you simply want to show a Button "Load Earlier Messages" at the top. You can simply create an xml for your load more Button, make that as the first row of your RecyclerView and create an Interface to handle click events. I am posting code for the Adpater from one of my projects. Hope that will help you in getting some idea to proceed further.
/**
* Created by Mukesh on 21/12/2015.
*/
public class ChatListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private List<UserMessage> userMessagesList;
private LayoutInflater mLayoutInflater;
private static final int ROW_TYPE_LOAD_EARLIER_MESSAGES = 0;
private static final int ROW_TYPE_SENDER = 1;
private static final int ROW_TYPE_RECEIVER = 2;
private int userId;
private boolean isLoadEarlierMsgs;
private LoadEarlierMessages mLoadEarlierMessages;
public ChatListAdapter(Context context, int userId, List<UserMessage> userMessagesList) {
mContext = context;
this.userMessagesList = userMessagesList;
mLayoutInflater = LayoutInflater.from(mContext);
this.userId = userId;
mLoadEarlierMessages = (LoadEarlierMessages) mContext;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case ROW_TYPE_LOAD_EARLIER_MESSAGES:
return new LoadEarlierMsgsViewHolder(mLayoutInflater.inflate(R.layout
.row_load_earlier_messages, parent, false));
case ROW_TYPE_SENDER:
return new SenderMsgViewHolder(mLayoutInflater.inflate(R.layout.row_sender_msg,
parent, false));
case ROW_TYPE_RECEIVER:
return new ReceiverMsgViewHolder(mLayoutInflater.inflate(R.layout
.row_receiver_msg, parent, false));
default:
return null;
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case ROW_TYPE_LOAD_EARLIER_MESSAGES:
LoadEarlierMsgsViewHolder loadEarlierMsgsViewHolder =
(LoadEarlierMsgsViewHolder) holder;
if (isLoadEarlierMsgs) {
loadEarlierMsgsViewHolder.btLoadEarlierMessages
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mLoadEarlierMessages != null) {
mLoadEarlierMessages.onLoadEarlierMessages();
}
}
});
} else {
loadEarlierMsgsViewHolder.btLoadEarlierMessages.setVisibility(View.GONE);
}
break;
case ROW_TYPE_SENDER:
SenderMsgViewHolder senderMsgViewHolder = (SenderMsgViewHolder) holder;
// set data for your sender chat bubble
break;
case ROW_TYPE_RECEIVER:
ReceiverMsgViewHolder receiverMsgViewHolder = (ReceiverMsgViewHolder) holder;
// set data for your receiver chat bubble
break;
}
}
#Override
public int getItemCount() {
return userMessagesList.size() + 1;
}
#Override
public int getItemViewType(int position) {
if (position == 0) {
return ROW_TYPE_LOAD_EARLIER_MESSAGES; // row load earlier messages
} else if (userMessagesList.get(position - 1).getUser_id() == userId) {
return ROW_TYPE_SENDER; // sender row;
} else {
return ROW_TYPE_RECEIVER; // receiver row;
}
}
public interface LoadEarlierMessages {
void onLoadEarlierMessages();
}
public void setLoadEarlierMsgs(boolean isLoadEarlierMsgs) {
this.isLoadEarlierMsgs = isLoadEarlierMsgs;
}
static class LoadEarlierMsgsViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.btLoadEarlierMsgs) Button btLoadEarlierMessages;
public LoadEarlierMsgsViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
static class SenderMsgViewHolder extends RecyclerView.ViewHolder {
public SenderMsgViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
static class ReceiverMsgViewHolder extends RecyclerView.ViewHolder {
public ReceiverMsgViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
And finally implement the LoadEarlierMessages listener in your ChatActivity and Override the onLoadEarlierMessages() method
/**
* Created by Mukesh on 21/12/2015.
*/
public class ChatActivity extends AppCompatActivity
implements ChatListAdapter.LoadEarlierMessages {
// getting users recent messages and init RecyclerView
private void showUserMessages() {
// initialising LayoutManager for RecyclerView and setting that to RecyclerView
mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.setStackFromEnd(true); // to start the list from bottom
rvChatsList.setLayoutManager(mLinearLayoutManager);
// initialising RecyclerView Adapter and setting that to the RecyclerView
mChatListAdapter = new ChatListAdapter(this, userId, userMessagesList);
rvChatsList.setAdapter(mChatListAdapter);
// getting count of friend/contact messages and toggling visibility of load more button accordingly
int count = mDataBaseHandler.getCountOfMessages(contactId);
if (count != 0) {
if (count > Constants.MESSAGES_LIMIT_FOR_LOCAL_DATABASE) {
mChatListAdapter.setLoadEarlierMsgs(true);
} else {
mChatListAdapter.setLoadEarlierMsgs(false);
}
userMessagesList.addAll(mDataBaseHandler.getAllMessagesOfContact(contactId));
mChatListAdapter.notifyDataSetChanged();
}
}
#Override
public void onLoadEarlierMessages() {
ArrayList<UserMessage> tempList = mDataBaseHandler
.getPreviousMessagesOfContact(contactId, userMessagesList.size());
if (tempList.size() > 0) {
if (tempList.size() < Constants.MESSAGES_LIMIT_FOR_LOCAL_DATABASE) {
mChatListAdapter.setLoadEarlierMsgs(false);
}
View v = rvChatsList.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
for (int i = 0; i < tempList.size(); i++) {
userMessagesList.add(0, tempList.get(i));
}
mChatListAdapter.notifyDataSetChanged();
mLinearLayoutManager.scrollToPositionWithOffset(tempList.size(), top);
} else {
mChatListAdapter.setLoadEarlierMsgs(false);
}
}
}
Hope this will help..!!
I have 2 different layouts which I want to use for my views in specific situations in a Recycler View. the user decides which layout should appear. how is it possible to change the layout of my views which are being shown in the recycler view at run time? I think I need to force my adapter to restart and recreate and rearrange the views. how to do that at a way that I don't lose my insert animation?
UPDATE:
public class InfinityFragmentRecyclerAdapter extends RecyclerView.Adapter implements HasDatabase
{
protected JsonDatabase jsonDatabase = new JsonDatabase(null);
protected Context mContext;
protected int arrangeMode;
public InfinityFragmentRecyclerAdapter(Context context, int viewMode)
{
mContext = context;
arrangeMode = viewMode;
}
// this is the method which enables me to change the view mode
public void setNewArrangeMode(int mode)
{
arrangeMode = mode;
notifyDataSetChanged();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i)
{
View view;
if (arrangeMode == SupportsGridAndListArrangement.GRID_VIEW)
{
view = LayoutInflater.from(viewGroup.getContext()).inflate
(R.layout.grid_layout, null);
}
else
{
view = LayoutInflater.from(viewGroup.getContext()).inflate
(R.layout.list_layout, null);
}
return new ItemHolder(view, mContext, arrangeMode);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i)
{
....
if (arrangeMode == SupportsGridAndListArrangement.LIST_VIEW)
{
...
StaggeredGridLayoutManager.LayoutParams layoutParams =
new StaggeredGridLayoutManager.LayoutParams
(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setFullSpan(true);
viewHolder.itemView.setLayoutParams(layoutParams);
}
}
#Override
public int getItemCount()
{
if (jsonDatabase != null)
{
return jsonDatabase.getCount();
}
else
{
return 0;
}
}
#Override
public Object getDatabase()
{
return jsonDatabase;
}
public void append(Object newJsonDatabase)
{
int currentCount = 0;
if (jsonDatabase != null)
{
currentCount = jsonDatabase.getCount();
}
int newCount = ((JsonDatabase) newJsonDatabase).getCount();
jsonDatabase.appendAtEnd((JsonDatabase) newJsonDatabase);
for (int i = currentCount; i < (currentCount + newCount); i++)
{
notifyItemInserted(i);
}
}
}