I am working on a chat app and I am very new to using ListViews and ArrayAdapters, as well as Custom Adapters. I am having a problem that causes all my items in my list to be of one layout, even they are supposed to change according to a booleans(true would be an outgoing chat bubble, and false would be an incoming chat bubble).
Here is my code for the retreival of the chat(It isn't the whole file, just a snippet):
Variable declarations:
final ArrayList<chatBubble> objects = new ArrayList<>();
final CustomAdapter customAdapter = new CustomAdapter(this, objects);
listView.setAdapter(customAdapter);
Code to get messages and add to list:
mDatabase.child("chat").child("publicDump").child("dumpedMessages").child("message" + i).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
final String message = dataSnapshot.getValue(String.class);
if (message != null) {
final String extract = message.substring(message.lastIndexOf("<") + 1, message.indexOf(">"));
mDatabase.child("users").child("c").child("emailToUsername").child(mAuth.getCurrentUser().getEmail().replace(".", ",")).child("username").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String username = dataSnapshot.getValue(String.class);
if (username != null) {
if (username.equals(extract)) {
Log.i("Extract", extract);
int semicnt = 0;
int num = 0;
//Log.i("Loop", "Yes");
for (int i = 0; i < message.length(); i++) {
//Log.i("Loop", "y");
if (String.valueOf(message.charAt(i)).equals(":")) {
semicnt++;
//Log.i("cnt", String.valueOf(semicnt));
if (semicnt == 3) {
num = i;
i = message.length() - 1;
String time = message.substring(0, (Math.min(message.length(), num)));
String finalM = message.replace(time + ": ", "").replace("<" + extract + "> ", "");
chatBubble chat = new chatBubble(finalM, "From: " + extract + " At: " + time, true);
objects.add(chat);
}
}
}
} else {
int semicnt = 0;
int num = 0;
// Log.i("Loop", "Yes");
for (int i = 0; i < message.length(); i++) {
//Log.i("Loop", "y");
if (String.valueOf(message.charAt(i)).equals(":")) {
semicnt++;
//Log.i("cnt", String.valueOf(semicnt));
if (semicnt == 3) {
num = i;
i = message.length() - 1;
String time = message.substring(0, (Math.min(message.length(), num)));
String finalM = message.replace(time + ": ", "").replace("<" + extract + "> ", "");
chatBubble chat = new chatBubble(finalM, "From: " + extract + " At: " + time, false);
objects.add(chat);
}
}
}
}
customAdapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here is my code for my chatBubble:
package com.tejasmehta.codeychat;
public class chatBubble {
private String msg;
private String date;
private boolean myMessage;
public chatBubble(String msg, String date, boolean myMessage) {
this.msg = msg;
this.date = date;
this.myMessage = myMessage;
}
public String Msg() {
return msg;
}
public String Date() {
return date;
}
public boolean myMessage() {
return myMessage;
}
}
And here is my code for my customAdapter(which shows that if the boolean, myMessage, is true, it will load a different layout, and a different one for false):
public class CustomAdapter extends BaseAdapter {
private LayoutInflater inflater;
private ArrayList<chatBubble> objects;
private class ViewHolder {
TextView msg;
TextView date;
}
public CustomAdapter(Context context, ArrayList<chatBubble> objects) {
inflater = LayoutInflater.from(context);
this.objects = objects;
}
public int getCount() {
return objects.size();
}
public chatBubble getItem(int position) {
return objects.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int layoutResource; // determined by view type
chatBubble ChatBubble = getItem(position);
if (ChatBubble.myMessage()) {
layoutResource = R.layout.right_bubble;
} else {
layoutResource = R.layout.left_bubble;
}
if(convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(layoutResource, null);
holder.msg = convertView.findViewById(R.id.txt_msg);
holder.date = convertView.findViewById(R.id.date);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.msg.setText(objects.get(position).Msg());
holder.date.setText(objects.get(position).Date());
return convertView;
}
}
Thank You for all of your help!
the problem is your getview
The view is being recycled so convertview already has a layout. so its not being reinflated to the correct layout.
you need to use getViewType() and getViewTypeCount() to tell the listview you want to use different layouts
http://android.amberfog.com/?p=296
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
return getItem(position).myMessage()?0:1;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int layoutResource; // determined by view type
chatBubble ChatBubble = getItem(position);
if (ChatBubble.myMessage()) {
layoutResource = R.layout.right_bubble;
} else {
layoutResource = R.layout.left_bubble;
}
if(convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(layoutResource, null);
holder.msg = convertView.findViewById(R.id.txt_msg);
holder.date = convertView.findViewById(R.id.date);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.msg.setText(objects.get(position).Msg());
holder.date.setText(objects.get(position).Date());
return convertView;
}
Related
I am trying to develop an activity where there is a custom listView made out of CustomAdapter.
The list consists of a TextView and an EditText. The EditText when clicked, it auto fetches the system time.
What I want is when a particular EditText is filled, I want all the previous(above) list items in the sequence to be disabled.
So far, I have tried using isEnabled() and areAllItemsEnabled() functions returning respective boolean values using position, but however didn’t work.
Please help me achieve the above.
Thanks.
This is my CustomAdapter Class
public class SelectStnListByRoute extends BaseAdapter implements View.OnClickListener {
Context context;
ArrayList<StnNames> stnList;
LayoutInflater layoutInflater = null;
ViewHolder viewHolder;
private int mLastClicked;
public SelectStnListByRoute(Context context, ArrayList<StnNames> stnList) {
super();
this.context = context;
this.stnList = stnList;
layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return stnList.size();
}
#Override
public Object getItem(int position) {
return stnList.get(position);
}
#Override
public long getItemId(int position) {
return stnList.indexOf(getItem(position));
}
public int getViewTypeCount() {
return 1;
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
if(position==position){
return false;
}
return false;
}
#Override
public View getView(final int position, View convertView, ViewGroup viewGroup) {
int type = getItemViewType(position);
StnNames stnDetails = stnList.get(position);
viewHolder = new ViewHolder();
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.footplate_custome_layout, null);
viewHolder.txtStnNAme = (TextView) convertView.findViewById(R.id.txtStnCode);
viewHolder.txtStnArr = (TextView) convertView.findViewById(R.id.txtArrivalTime);
viewHolder.txtStnDep = (TextView) convertView.findViewById(R.id.txtDepTime);
convertView.setTag(viewHolder);
viewHolder.txtStnArr.setTag(stnDetails);
viewHolder.txtStnDep.setTag(stnDetails);
} else {
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.txtStnArr.setTag(stnDetails);
viewHolder.txtStnDep.setTag(stnDetails);
}
viewHolder.txtStnNAme.setText(stnDetails.getStnCode());
viewHolder.txtStnArr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("Position: " , String.valueOf(position)); //Here I am getting the position of the row item clicked, where should I put the Onclick false for disabling all of the above fields using the position?
}
});
viewHolder.txtStnDep.setOnClickListener(this);
viewHolder.txtStnArr = (TextView) convertView.findViewById(R.id.txtArrivalTime);
if (stnDetails.getArrivalTime() != null) {
viewHolder.txtStnArr.setText(stnDetails.getArrivalTime());
} else {
viewHolder.txtStnArr.setText("");
}
if (stnDetails.getDeptTime() != null) {
viewHolder.txtStnDep.setText(stnDetails.getDeptTime());
} else {
viewHolder.txtStnDep.setText("");
}
return convertView;
}
class ViewHolder {
TextView txtStnNAme, txtStnArr, txtStnDep;
int ref;
}
#Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case txtArrivalTime:
TextView textViewArrVal = (TextView) view.findViewById(R.id.txtArrivalTime);
textViewArrVal.setClickable(false);
StnNames listItemsArrr = (StnNames) textViewArrVal.getTag();
if (listItemsArrr.getArrivalTime() != getCurrentTime()) {
listItemsArrr.setArrivalTime(getCurrentTime());
if (listItemsArrr.getArrivalTime() != null) {
int position = textViewArrVal.getSelectionStart();
textViewArrVal.setText(listItemsArrr.getArrivalTime());
} else {
textViewArrVal.setText("");
}
}
break;
case txtDepTime:
TextView textViewDepVal = (TextView) view.findViewById(R.id.txtDepTime);
StnNames listItemsDepp = (StnNames) textViewDepVal.getTag();
if (listItemsDepp.getDeptTime() != getCurrentTime()) {
listItemsDepp.setDeptTime(getCurrentTime());
if (listItemsDepp.getDeptTime() != null) {
textViewDepVal.setText(listItemsDepp.getDeptTime());
} else {
textViewDepVal.setText("");
}
}
break;
default:
break;
}
}
public String getCurrentTime(){
Calendar calendar = Calendar.getInstance();
SimpleDateFormat mdformat = new SimpleDateFormat("HH:mm:ss");
String arrDate = mdformat.format(calendar.getTime());
return arrDate;
}
}
You can do this as below mentioned -:
You need to store the position of clicked button was. So initialize a variable in your class
int mButtonSelected = -1;
EDIT 1.
Then make a change to your isEnabled method
#Override
public boolean isEnabled(int position) {
if(position<mButtonSelected){
return false;
}
return true;
}
That will work it if any other button was clicked. but you have to do that in your onClick
mButtonSelected = position;
notifyDataSetChanged();
Let me it worked or not
EDIT
see below changes in your code-:
public class SelectStnListByRoute extends BaseAdapter {
Context context;
ArrayList<StnNames> stnList;
LayoutInflater layoutInflater = null;
ViewHolder viewHolder;
private int mLastClicked;
private SQLiteDB sqLiteDB;
int mArrivalSelected = -1;
int mDepartSelected = -1;
public SelectStnListByRoute(Context context, ArrayList<StnNames> stnList) {
super();
this.context = context;
this.stnList = stnList;
layoutInflater = LayoutInflater.from(context);
sqLiteDB = new SQLiteDB(context);
}
#Override
public int getCount() {
return stnList.size();
}
#Override
public Object getItem(int position) {
return stnList.get(position);
}
#Override
public long getItemId(int position) {
return stnList.indexOf(getItem(position));
}
public int getViewTypeCount() {
return 1;
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
if (position <= mArrivalSelected) {
return false;
}
return true;
}
public boolean isEnabledd(int position) {
if (position <= mDepartSelected) {
return false;
}
return true;
}
#Override
public View getView(final int position, View convertView, ViewGroup viewGroup) {
int type = getItemViewType(position);
StnNames stnDetails = stnList.get(position);
viewHolder = new ViewHolder();
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.footplate_custome_layout, null);
viewHolder.txtStnNAme = (TextView) convertView.findViewById(R.id.txtStnCode);
viewHolder.txtStnArr = (TextView) convertView.findViewById(R.id.txtArrivalTime);
viewHolder.txtStnDep = (TextView) convertView.findViewById(R.id.txtDepTime);
convertView.setTag(viewHolder);
viewHolder.txtStnArr.setTag(stnDetails);
viewHolder.txtStnDep.setTag(stnDetails);
} else {
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.txtStnArr.setTag(stnDetails);
viewHolder.txtStnDep.setTag(stnDetails);
}
viewHolder.txtStnNAme.setText(stnDetails.getStnCode());
if (!isEnabled(position)) {
if (position <= mArrivalSelected) {
viewHolder.txtStnArr.setBackgroundColor(Color.parseColor("#ffa500"));
viewHolder.txtStnArr.setEnabled(false);
if (position < mArrivalSelected) {
viewHolder.txtStnDep.setEnabled(false);
viewHolder.txtStnDep.setBackgroundColor(Color.parseColor("#ffa500"));
}
}
} else {
viewHolder.txtStnArr.setEnabled(true);
viewHolder.txtStnDep.setEnabled(true);
viewHolder.txtStnArr.setBackgroundColor(Color.parseColor("#b4b4b4"));
viewHolder.txtStnDep.setBackgroundColor(Color.parseColor("#b4b4b4"));
}
viewHolder.txtStnArr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("Position: ", String.valueOf(position));
mArrivalSelected = position;
arrivalClick(view);
notifyDataSetChanged();
}
});
if (!isEnabledd(position)) {
if (position <= mDepartSelected) {
viewHolder.txtStnArr.setBackgroundColor(Color.parseColor("#ffa500"));
viewHolder.txtStnDep.setBackgroundColor(Color.parseColor("#ffa500"));
viewHolder.txtStnArr.setEnabled(false);
viewHolder.txtStnDep.setEnabled(false);
} else {
viewHolder.txtStnArr.setEnabled(true);
viewHolder.txtStnDep.setEnabled(true);
viewHolder.txtStnArr.setBackgroundColor(Color.parseColor("#b4b4b4"));
viewHolder.txtStnDep.setBackgroundColor(Color.parseColor("#b4b4b4"));
}
}
viewHolder.txtStnDep.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("Position: ", String.valueOf(position));
mDepartSelected = position;
departureClick(view);
notifyDataSetChanged();
}
});
viewHolder.txtStnArr = (TextView) convertView.findViewById(R.id.txtArrivalTime);
if (stnDetails.getArrivalTime() != null) {
viewHolder.txtStnArr.setText(stnDetails.getArrivalTime());
} else {
viewHolder.txtStnArr.setText("");
}
if (stnDetails.getDeptTime() != null) {
viewHolder.txtStnDep.setText(stnDetails.getDeptTime());
} else {
viewHolder.txtStnDep.setText("");
}
return convertView;
}
class ViewHolder {
TextView txtStnNAme, txtStnArr, txtStnDep;
StnNames pos;
int ref;
}
public void arrivalClick(View view) {
TextView textViewArrVal = (TextView) view.findViewById(R.id.txtArrivalTime);
StnNames listItemsArrr = (StnNames) textViewArrVal.getTag();
if (listItemsArrr.getArrivalTime() != getCurrentTime()) {
listItemsArrr.setArrivalTime(getCurrentTime());
int stnId = listItemsArrr.getStnId();
String arrClick = "arrival";
String upSideKm = listItemsArrr.getStnUpsideKm();
String downsideKm = listItemsArrr.getStnDownSideKm();
String arrTime = getCurrentTime();
/* sqLiteDB.open();
*//* long abc = sqLiteDB.insertJourneySchedule(stnId,arrTime,"",userId,journeyId,latitute,longitute,journyDate,arrClick);*//*
*//* long abcd = sqLiteDB.updateJourneySchedule(stnId,arrTime,"",userId,journeyId,latitute,longitute,journyDate,arrClick,downsideKm,upSideKm);
Log.e("arrclick",String.valueOf(abcd));*//*
sqLiteDB.close();*/
if (listItemsArrr.getArrivalTime() != null) {
int position = textViewArrVal.getSelectionStart();
textViewArrVal.setText(listItemsArrr.getArrivalTime());
} else {
textViewArrVal.setText("");
}
}
}
public void departureClick(View view) {
TextView textViewDepVal = (TextView) view.findViewById(R.id.txtDepTime);
StnNames listItemsDepp = (StnNames) textViewDepVal.getTag();
if (listItemsDepp.getDeptTime() != getCurrentTime()) {
listItemsDepp.setDeptTime(getCurrentTime());
String depTime = getCurrentTime();
int stnId = listItemsDepp.getStnId();
String depClick = "departure";
String upSideKm = listItemsDepp.getStnUpsideKm();
String downsideKm = listItemsDepp.getStnDownSideKm();
sqLiteDB.open();
/*long abc = sqLiteDB.insertJourneySchedule(stnId,"",depTime,userId,journeyId,latitute,longitute,journyDate,depClick);*/
/*long abcd = sqLiteDB.updateJourneySchedule(stnId,"",depTime,userId,journeyId,latitute,longitute,journyDate,depClick,downsideKm,upSideKm);
Log.e("depclick",String.valueOf(abcd));*/
sqLiteDB.close();
if (listItemsDepp.getDeptTime() != null) {
textViewDepVal.setText(listItemsDepp.getDeptTime());
} else {
textViewDepVal.setText("");
}
}
}
public String getCurrentTime() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat mdformat = new SimpleDateFormat("HH:mm:ss");
String arrDate = mdformat.format(calendar.getTime());
return arrDate;
}
}
Get the position of the row which is clicked and then set onclick false for positions less than clicked position
as follows:
viewHolder.txtStnArr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("Position: " , String.valueOf(position));
for (int i = 0; i < position; i++) {
viewHolder.txtStnArr.setEnable(false);
}
notifyDataSetChanged();
}
});
Below is my complete adapter class of sendbird chatting.Currently date with time is displayed with every message.viewHolder.getView("left_time") and viewHolder.getView("right_time") are views for displaying date with time and it is calculated in method getDisplayDateTime.I want date with time to be displayed only when there is a change in date.For example if there is set of messages dated 23rd june then date with time should be displayed only for the first message with date 23rd june.
I tried doing that by detecting whenever there is a change in date by storing date in xyz variable and comparing it with date of every message and whenever they are unequal then making date view of that message visible and assigning the new date to xyz variable for comparison with future messages.But this approach fails when i scroll down and scroll up list.
What is the ideal approach for achieving this?
public class SendBirdMessagingAdapter extends BaseAdapter {
private static final int TYPE_UNSUPPORTED = 0;
private static final int TYPE_MESSAGE = 1;
private static final int TYPE_SYSTEM_MESSAGE = 2;
private static final int TYPE_FILELINK = 3;
private static final int TYPE_BROADCAST_MESSAGE = 4;
private static final int TYPE_TYPING_INDICATOR = 5;
private final Context mContext;
private final LayoutInflater mInflater;
private final ArrayList<Object> mItemList;
private Hashtable<String, Long> mReadStatus;
private Hashtable<String, Long> mTypeStatus;
private List<MessagingChannel.Member> mMembers;
private long mMaxMessageTimestamp = Long.MIN_VALUE;
private long mMinMessageTimestamp = Long.MAX_VALUE;
public SendBirdMessagingAdapter(Context context) {
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mItemList = new ArrayList<Object>();
mReadStatus = new Hashtable<String, Long>();
mTypeStatus = new Hashtable<String, Long>();
}
#Override
public int getCount() {
return mItemList.size() + ((mTypeStatus.size() <= 0) ? 0 : 1);
}
#Override
public Object getItem(int position) {
if (position >= mItemList.size()) {
ArrayList<String> names = new ArrayList<String>();
for (MessagingChannel.Member member : mMembers) {
if (mTypeStatus.containsKey(member.getId())) {
names.add(member.getName());
}
}
return names;
}
return mItemList.get(position);
}
public void delete(Object object) {
mItemList.remove(object);
}
public void clear() {
mMaxMessageTimestamp = Long.MIN_VALUE;
mMinMessageTimestamp = Long.MAX_VALUE;
mReadStatus.clear();
mTypeStatus.clear();
mItemList.clear();
}
public void resetReadStatus(Hashtable<String, Long> readStatus) {
mReadStatus = readStatus;
}
public void setReadStatus(String userId, long timestamp) {
if (mReadStatus.get(userId) == null || mReadStatus.get(userId) < timestamp) {
mReadStatus.put(userId, timestamp);
}
}
public void setTypeStatus(String userId, long timestamp) {
if (userId.equals(SendBird.getUserId())) {
return;
}
if (timestamp <= 0) {
mTypeStatus.remove(userId);
} else {
mTypeStatus.put(userId, timestamp);
}
}
#Override
public long getItemId(int position) {
return position;
}
public void addMessageModel(MessageModel messageModel) {
if (messageModel.isPast()) {
mItemList.add(0, messageModel);
} else {
mItemList.add(messageModel);
}
updateMessageTimestamp(messageModel);
}
private void updateMessageTimestamp(MessageModel model) {
mMaxMessageTimestamp = mMaxMessageTimestamp < model.getTimestamp() ? model.getTimestamp() : mMaxMessageTimestamp;
mMinMessageTimestamp = mMinMessageTimestamp > model.getTimestamp() ? model.getTimestamp() : mMinMessageTimestamp;
}
public long getMaxMessageTimestamp() {
return mMaxMessageTimestamp == Long.MIN_VALUE ? Long.MAX_VALUE : mMaxMessageTimestamp;
}
public long getMinMessageTimestamp() {
return mMinMessageTimestamp == Long.MAX_VALUE ? Long.MIN_VALUE : mMinMessageTimestamp;
}
public void setMembers(List<MessagingChannel.Member> members) {
mMembers = members;
}
#Override
public int getItemViewType(int position) {
if (position >= mItemList.size()) {
return TYPE_TYPING_INDICATOR;
}
Object item = mItemList.get(position);
if (item instanceof Message) {
return TYPE_MESSAGE;
} else if (item instanceof FileLink) {
return TYPE_FILELINK;
} else if (item instanceof SystemMessage) {
return TYPE_SYSTEM_MESSAGE;
} else if (item instanceof BroadcastMessage) {
return TYPE_BROADCAST_MESSAGE;
}
return TYPE_UNSUPPORTED;
}
#Override
public int getViewTypeCount() {
return 6;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
final Object item = getItem(position);
if (convertView == null || ((ViewHolder) convertView.getTag()).getViewType() != getItemViewType(position)) {
viewHolder = new ViewHolder();
viewHolder.setViewType(getItemViewType(position));
switch (getItemViewType(position)) {
case TYPE_UNSUPPORTED:
convertView = new View(mInflater.getContext());
convertView.setTag(viewHolder);
break;
case TYPE_MESSAGE: {
TextView tv;
CircularImageView iv;
View v;
convertView = mInflater.inflate(R.layout.sendbird_view_messaging_message, parent, false);
v = convertView.findViewById(R.id.left_container);
viewHolder.setView("left_container", v);
iv = (CircularImageView) convertView.findViewById(R.id.img_left_thumbnail);
viewHolder.setView("left_thumbnail", iv);
tv = (TextView) convertView.findViewById(R.id.txt_left);
viewHolder.setView("left_message", tv);
tv = (TextView) convertView.findViewById(R.id.txt_left_name);
viewHolder.setView("left_name", tv);
tv = (TextView) convertView.findViewById(R.id.txt_left_time);
viewHolder.setView("left_time", tv);
v = convertView.findViewById(R.id.right_container);
viewHolder.setView("right_container", v);
iv = (CircularImageView) convertView.findViewById(R.id.img_right_thumbnail);
viewHolder.setView("right_thumbnail", iv);
tv = (TextView) convertView.findViewById(R.id.txt_right);
viewHolder.setView("right_message", tv);
tv = (TextView) convertView.findViewById(R.id.txt_right_name);
viewHolder.setView("right_name", tv);
tv = (TextView) convertView.findViewById(R.id.txt_right_time);
viewHolder.setView("right_time", tv);
tv = (TextView) convertView.findViewById(R.id.txt_right_status);
viewHolder.setView("right_status", tv);
convertView.setTag(viewHolder);
break;
}
case TYPE_SYSTEM_MESSAGE: {
convertView = mInflater.inflate(R.layout.sendbird_view_system_message, parent, false);
viewHolder.setView("message", convertView.findViewById(R.id.txt_message));
convertView.setTag(viewHolder);
break;
}
case TYPE_BROADCAST_MESSAGE: {
convertView = mInflater.inflate(R.layout.sendbird_view_system_message, parent, false);
viewHolder.setView("message", convertView.findViewById(R.id.txt_message));
convertView.setTag(viewHolder);
break;
}
case TYPE_FILELINK: {
TextView tv;
CircularImageView civ;
ImageView iv;
View v;
convertView = mInflater.inflate(R.layout.sendbird_view_messaging_filelink, parent, false);
v = convertView.findViewById(R.id.left_container);
viewHolder.setView("left_container", v);
civ = (CircularImageView) convertView.findViewById(R.id.img_left_thumbnail);
viewHolder.setView("left_thumbnail", civ);
iv = (ImageView) convertView.findViewById(R.id.img_left);
viewHolder.setView("left_image", iv);
tv = (TextView) convertView.findViewById(R.id.txt_left_name);
viewHolder.setView("left_name", tv);
tv = (TextView) convertView.findViewById(R.id.txt_left_time);
viewHolder.setView("left_time", tv);
v = convertView.findViewById(R.id.right_container);
viewHolder.setView("right_container", v);
civ = (CircularImageView) convertView.findViewById(R.id.img_right_thumbnail);
viewHolder.setView("right_thumbnail", civ);
iv = (ImageView) convertView.findViewById(R.id.img_right);
viewHolder.setView("right_image", iv);
tv = (TextView) convertView.findViewById(R.id.txt_right_name);
viewHolder.setView("right_name", tv);
tv = (TextView) convertView.findViewById(R.id.txt_right_time);
viewHolder.setView("right_time", tv);
tv = (TextView) convertView.findViewById(R.id.txt_right_status);
viewHolder.setView("right_status", tv);
convertView.setTag(viewHolder);
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new AlertDialog.Builder(mContext)
.setTitle("Foodvite")
.setMessage("Do you want to download this file?")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
try {
downloadUrl((FileLink) item, mContext);
} catch (IOException e) {
e.printStackTrace();
}
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create()
.show();
}
});
break;
}
case TYPE_TYPING_INDICATOR: {
convertView = mInflater.inflate(R.layout.sendbird_view_typing_indicator, parent, false);
viewHolder.setView("message", convertView.findViewById(R.id.txt_message));
convertView.setTag(viewHolder);
break;
}
}
}
viewHolder = (ViewHolder) convertView.getTag();
switch (getItemViewType(position)) {
case TYPE_UNSUPPORTED:
break;
case TYPE_MESSAGE:
Message message = (Message) item;
if (message.getSenderId().equals(SendBird.getUserId())) {
viewHolder.getView("left_container", View.class).setVisibility(View.GONE);
viewHolder.getView("right_container", View.class).setVisibility(View.VISIBLE);
displayUrlImage(viewHolder.getView("right_thumbnail", CircularImageView.class), message.getSenderImageUrl(), true);
viewHolder.getView("right_name", TextView.class).setText(message.getSenderName());
viewHolder.getView("right_message", TextView.class).setText(message.getMessage());
viewHolder.getView("right_time", TextView.class).setText(getDisplayDateTime(mContext, message.getTimestamp()));
int readCount = 0;
for (String key : mReadStatus.keySet()) {
if (key.equals(message.getSenderId())) {
readCount += 1;
continue;
}
if (mReadStatus.get(key) >= message.getTimestamp()) {
readCount += 1;
}
}
if (readCount < mReadStatus.size()) {
if (mReadStatus.size() - readCount > 1) {
viewHolder.getView("right_status", TextView.class).setText("Unread " + (mReadStatus.size() - readCount));
} else {
viewHolder.getView("right_status", TextView.class).setText("Unread");
}
} else {
viewHolder.getView("right_status", TextView.class).setText("");
}
viewHolder.getView("right_container").setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
new AlertDialog.Builder(mContext)
.setTitle("Foodvite")
.setMessage("Do you want to delete a message?")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
SendBird.deleteMessage(((Message) item).getMessageId(), new DeleteMessageHandler() {
#Override
public void onError(SendBirdException e) {
e.printStackTrace();
}
#Override
public void onSuccess(long messageId) {
mSendBirdMessagingAdapter.delete(item);
mSendBirdMessagingAdapter.notifyDataSetChanged();
Toast.makeText(mContext, "Message has been deleted.", Toast.LENGTH_SHORT).show();
}
});
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create()
.show();
return true;
}
});
} else {
viewHolder.getView("left_container", View.class).setVisibility(View.VISIBLE);
viewHolder.getView("right_container", View.class).setVisibility(View.GONE);
displayUrlImage(viewHolder.getView("left_thumbnail", CircularImageView.class), message.getSenderImageUrl(), true);
viewHolder.getView("left_name", TextView.class).setText(message.getSenderName());
viewHolder.getView("left_message", TextView.class).setText(message.getMessage());
viewHolder.getView("left_time", TextView.class).setText(getDisplayDateTime(mContext, message.getTimestamp()));
if(isGroupChat)
viewHolder.getView("left_name", TextView.class).setVisibility(View.VISIBLE);
else
viewHolder.getView("left_name", TextView.class).setVisibility(View.GONE);
}
break;
case TYPE_SYSTEM_MESSAGE:
SystemMessage systemMessage = (SystemMessage) item;
viewHolder.getView("message", TextView.class).setText(Html.fromHtml(systemMessage.getMessage()));
break;
case TYPE_BROADCAST_MESSAGE:
BroadcastMessage broadcastMessage = (BroadcastMessage) item;
viewHolder.getView("message", TextView.class).setText(Html.fromHtml(broadcastMessage.getMessage()));
break;
case TYPE_FILELINK:
FileLink fileLink = (FileLink) item;
if (fileLink.getSenderId().equals(SendBird.getUserId())) {
viewHolder.getView("left_container", View.class).setVisibility(View.GONE);
viewHolder.getView("right_container", View.class).setVisibility(View.VISIBLE);
displayUrlImage(viewHolder.getView("right_thumbnail", ImageView.class), fileLink.getSenderImageUrl(), true);
viewHolder.getView("right_name", TextView.class).setText(fileLink.getSenderName());
if (fileLink.getFileInfo().getType().toLowerCase().startsWith("image")) {
displayUrlImage(viewHolder.getView("right_image", ImageView.class), fileLink.getFileInfo().getUrl());
} else {
viewHolder.getView("right_image", CircularImageView.class).setImageResource(R.drawable.sendbird_icon_file);
}
viewHolder.getView("right_time", TextView.class).setText(getDisplayDateTime(mContext, fileLink.getTimestamp()));
int readCount = 0;
for (String key : mReadStatus.keySet()) {
if (key.equals(fileLink.getSenderId())) {
continue;
}
if (mReadStatus.get(key) < fileLink.getTimestamp()) {
readCount += 1;
}
}
if (readCount < mReadStatus.size() - 1) {
viewHolder.getView("right_status", TextView.class).setText("Unread");
} else {
viewHolder.getView("right_status", TextView.class).setText("");
}
} else {
viewHolder.getView("left_container", View.class).setVisibility(View.VISIBLE);
viewHolder.getView("right_container", View.class).setVisibility(View.GONE);
displayUrlImage(viewHolder.getView("left_thumbnail", ImageView.class), fileLink.getSenderImageUrl(), true);
viewHolder.getView("left_name", TextView.class).setText(fileLink.getSenderName());
if (fileLink.getFileInfo().getType().toLowerCase().startsWith("image")) {
displayUrlImage(viewHolder.getView("left_image", ImageView.class), fileLink.getFileInfo().getUrl());
} else {
viewHolder.getView("left_image", CircularImageView.class).setImageResource(R.drawable.sendbird_icon_file);
}
if(isGroupChat)
viewHolder.getView("left_name", TextView.class).setVisibility(View.VISIBLE);
else
viewHolder.getView("left_name", TextView.class).setVisibility(View.GONE);
viewHolder.getView("left_time", TextView.class).setText(getDisplayDateTime(mContext, fileLink.getTimestamp()));
}
break;
case TYPE_TYPING_INDICATOR: {
int itemCount = ((List) item).size();
String typeMsg = ((List) item).get(0)
+ ((itemCount > 1) ? " +" + (itemCount - 1) : "")
+ ((itemCount > 1) ? " are " : " is ")
+ "typing...";
viewHolder.getView("message", TextView.class).setText(typeMsg);
break;
}
}
return convertView;
}
public boolean checkTypeStatus() {
/**
* Clear an old type status.
*/
for (String key : mTypeStatus.keySet()) {
Long ts = mTypeStatus.get(key);
if (System.currentTimeMillis() - ts > 10 * 1000L) {
mTypeStatus.remove(key);
return true;
}
}
return false;
}
private class ViewHolder {
private Hashtable<String, View> holder = new Hashtable<String, View>();
private int type;
public int getViewType() {
return this.type;
}
public void setViewType(int type) {
this.type = type;
}
public void setView(String k, View v) {
holder.put(k, v);
}
public View getView(String k) {
return holder.get(k);
}
public <T> T getView(String k, Class<T> type) {
return type.cast(getView(k));
}
}
}
private static String getDisplayDateTime(Context context, long milli) {
Date date = new Date(milli);
if (System.currentTimeMillis() - milli < 60 * 60 * 24 * 1000l) {
return DateFormat.getTimeFormat(context).format(date);
}
return DateFormat.getDateFormat(context).format(date) + " " + DateFormat.getTimeFormat(context).format(date);
}
Try below code for your method,
private static String getDisplayDateTime(Context context, long milli, long milli2)
{
Date date = new Date(milli);
Date previousDate = new Date(milli2);
String strCurrentDate = "", strPreviousDate = "";
if (System.currentTimeMillis() - milli < 60 * 60 * 24 * 1000l)
{
strCurrentDate = DateFormat.getTimeFormat(context).format(date);
if(milli2 != -1)
strPreviousDate = DateFormat.getTimeFormat(context).format(previousDate);
//return strCurrentDate.equals(strPreviousDate) ? "" : strCurrentDate;
}
else
{
strCurrentDate = DateFormat.getDateFormat(context).format(date) + " " + DateFormat.getTimeFormat(context).format(date);
if(milli2 != -1)
strPreviousDate = DateFormat.getDateFormat(context).format(strPreviousDate) + " " + DateFormat.getTimeFormat(context).format(strPreviousDate);
}
return strCurrentDate.equals(strPreviousDate) ? "" : strCurrentDate;
}
Now call your methods like below
if(position > 0)
{
final Object previousItem = getItem(position - 1);
Message previousMessage = (Message) previousItem;
viewHolder.getView("right_time", TextView.class).setText(getDisplayDateTime(mContext, message.getTimestamp(), previousMessage.getTimestamp()));
}
else
{
viewHolder.getView("right_time", TextView.class).setText(getDisplayDateTime(mContext, message.getTimestamp(), -1));
}
I had a similar problem (ref this SO Question) few months ago and nothing worked except extending from ArrayAdapter<MyObject> instead of BaseAdapter.
So, change the base class of your adapter to ArrayAdapter<MyObject> and implement the prompted method of the abstract class. you might need to move some you your existing code to these overridden methods for better performance.
You can force the system to redraw all items by calling BaseAdapter.notifyDataSetChanged()
I have made a custom adapter to populate my gridView. What I am doing is that i am trying to populate the gridview with two different data(that too are custom) which are: Movies and FavouriteMovies. when the dridview is updated using Movies it updates just fine but when it FavouriteMovies it does not. I am storing FavouriteMovies in a sqlite db and then querying it to return a cursor.the data returns perfectly and there is no error. the main problem is with my MoviesAdapter. inside this when i add Movies to adapter it adds to the list inside MoviesAdapter and it works perfectly but when I add FavouriteMovies to the adapter it does not add it inside the favouriteList inside MoviesAdapter and its size is always zero.
please help!!
here is my MoviesAdapter:
package com.akshitjain.popularmovies;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
public class MoviesAdapter extends BaseAdapter {
private Context mContext;
List<Movies> list = new ArrayList<>();
List<FavouriteMovies> favouriteList = new ArrayList<>();
public MoviesAdapter(Context c) {
this.mContext = c;
}
#Override
public int getCount() {
if (list != null)
return list.size();
else
return favouriteList.size();
}
#Override
public Object getItem(int position) {
if (list != null)
return list.get(position);
else
return favouriteList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.grid_item_movies, parent, false);
}
ImageView moviePoster = (ImageView) convertView.findViewById(R.id.grid_item_movie_image);
if (list != null) {
Movies movies = list.get(position);
String posterPath = movies.posterPath;
final String POSTER_FINAL_URL = Constants.IMAGE_BASE_URL + Constants.POSTER_SIZE_LARGE + posterPath;
Picasso.with(mContext).load(POSTER_FINAL_URL.trim()).into(moviePoster);
} else {
FavouriteMovies favouriteMovies = favouriteList.get(position);
byte[] bb = favouriteMovies.posterImage;
moviePoster.setImageBitmap(BitmapFactory.decodeByteArray(bb, 0, bb.length));
}
return convertView;
}
public void add(Movies movies) {
list.add(movies);
}
public void offlineAdd(FavouriteMovies favouriteMovies) {
favouriteList.add(favouriteMovies);
}
public void clear() {
list.clear();
}
}
and here is where I am adding to the adapter:
#Override
protected void onPostExecute(Movies[] strings) {
if (strings != null) {
mMoviesAdapter.clear();
for (Movies moviesStr : strings) {
mMoviesAdapter.add(moviesStr);
}
}else if(mFavouriteMovies != null){
mMoviesAdapter.clear();
for(FavouriteMovies favouriteMoviesStr : mFavouriteMovies){
mMoviesAdapter.offlineAdd(favouriteMoviesStr);
}
}
Log.v("FetchMoviesTask","Count :" + mMoviesAdapter.getItem(0));
mMoviesAdapter.notifyDataSetChanged();
}
So sorry for my crude language.
You will always have count == 0 if you set your favorite movies.
List<Movies> list = new ArrayList<>();
#Override
public int getCount() {
if (list != null)
return list.size();
else
return favouriteList.size();
}
This will always return a count of 0 since list never is null. You favorite movies get ignored.
Solutions
Since you are only displaying either movies or favorites you should use 2 adapters. If you don't want to do this,
Use a boolean. Just set showFavorites to true, and display those. Or if you keep your null checks,
set the List<Movie> = null; when displaying favorited, then it will also work.
use following adapter:-
boolean[] CheckedItem_Adap;
ImageLoader imgload;
int headercount = 0, childCount;
LinkedList<HashMap<String, String>> allData;
LinkedList<HashMap<String, String>> temp_Header;
LinkedList<HashMap<String, String>> temp_child = new LinkedList<HashMap<String, String>>();
ArrayList<String> header;
ArrayList<String> childCount1;
private int[] mSectionIndices;
private String[] mSectionLetters;
private LayoutInflater inflater;
private Activity context;
public Adapter_UserTimeLine_StickyGrid(Activity context1, LinkedList<HashMap<String, String>> list, boolean[] checkedItems, ArrayList<String> childCountArray, ArrayList<String> headerarray, LinkedList<HashMap<String, String>> temp_Headers_LinkList) {
this.CheckedItem_Adap = checkedItems;
allData = list;
inflater = LayoutInflater.from(context1);
imgload = new ImageLoader(context1);
childCount1 = childCountArray;
header = headerarray;
temp_Header = temp_Headers_LinkList;
context = context1;
}
#Override
public int getCount() {
return allData.size();
}
#Override
public Object getItem(int position) {
return allData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder = new ViewHolder();
if (convertView == null) {
convertView = inflater.inflate(R.layout.sticky_listitems, parent, false);
}
holder.ivPostPic_Sticky = (ImageView) convertView.findViewById(R.id.ivPostPic_Sticky);
holder.ivSelectedToDelete_Sticky = (ImageView) convertView.findViewById(R.id.ivSelectedToDelete_Sticky);
holder.rlPostSticky_ManageSticky = (RelativeLayout) convertView.findViewById(R.id.rlPostSticky_ManageSticky);
if (CheckedItem_Adap[position] == true) {
holder.ivSelectedToDelete_Sticky.setVisibility(View.VISIBLE);
} else if (CheckedItem_Adap[position] == false) {
holder.ivSelectedToDelete_Sticky.setVisibility(View.GONE);
}
if (allData.get(position).get("media_type").equals("text")) {
holder.ivPostPic_Sticky.setImageResource(R.drawable.line_small);
} else {
imgload.DisplayImage(Constants.Imge_baseUrl + allData.get(position).get("video_thumb"),
holder.ivPostPic_Sticky);
}
holder.rlPostSticky_ManageSticky.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (UserTimeLine_Activity.isDeleteSelected) {
if (CheckedItem_Adap[position] == false) {
UserTimeLine_Activity.Selected_PostIds.add(allData.get(position).get("post_id"));
holder.ivSelectedToDelete_Sticky.setVisibility(View.VISIBLE);
CheckedItem_Adap[position] = true;
} else {
UserTimeLine_Activity.Selected_PostIds.remove(allData.get(position).get("post_id"));
holder.ivSelectedToDelete_Sticky.setVisibility(View.GONE);
CheckedItem_Adap[position] = false;
}
for (int i = 0; i < UserTimeLine_Activity.Selected_PostIds.size(); i++) {
Log.e("postid", i + "-" + UserTimeLine_Activity.Selected_PostIds.get(i) + "");
}
if (UserTimeLine_Activity.Selected_PostIds.get(0).equals(UserTimeLine_Activity.Selected_PostIds.get(0))) { }
} else {
String media_type = allData.get(position).get("media_type");
String post_id = allData.get(position).get("post_id");
Intent in = new Intent(context, PostDetails_UserOwn_TimeLIne_Activity.class);
in.putExtra("media_type", media_type);
in.putExtra("post_id", post_id);
in.putExtra("position", String.valueOf(position));
in.putExtra("post_User_Name", allData.get(position).get("post_User_Name"));
context.startActivity(in);
}
}
});
return convertView;
}
#Override
public int getCountForHeader(int i) {
int c = Integer.valueOf(childCount1.get(i));
return c;
}
#Override
public int getNumHeaders() {
return temp_Header.size();
}
#Override
public View getHeaderView(int position, View convertView, ViewGroup parent) {
HeaderViewHolder holder = new HeaderViewHolder();
if (convertView == null) {
convertView = inflater.inflate(R.layout.headersticky_managepost, parent, false);
}
temp_Header.get(position).get("post_datetime");
TextView tvDate_Sticky = (TextView) convertView.findViewById(R.id.tvDate_Sticky);
for (int i = 0; i < temp_Header.size(); i++) {
}
String Date = temp_Header.get(position).get("post_datetime");
String FormatedDate = parseDateToddMMyyyy(Date);
tvDate_Sticky.setText(FormatedDate);
return convertView;
}
public String parseDateToddMMyyyy(String time) {
String inputPattern = "yyyy-MM-dd";
String outputPattern = "MMM-dd-yyyy";
SimpleDateFormat inputFormat = new SimpleDateFormat(inputPattern);
SimpleDateFormat outputFormat = new SimpleDateFormat(outputPattern);
Date date = null;
String str = null;
try {
date = inputFormat.parse(time);
str = outputFormat.format(date);
} catch (ParseException e) {
e.printStackTrace();
}
return str;
}
class HeaderViewHolder {
TextView tvDate_Sticky;
}
class ViewHolder {
ImageView ivPostPic_Sticky, ivSelectedToDelete_Sticky;
RelativeLayout rlPostSticky_ManageSticky;
}
}
I have an issue in RecycleView. My screen has two tabs, both tabs contain recycleview.It call normally most of the time but sometimes give empty screen. Just I wrote log & system.out and found this issue. I will paste my adapter class code here.
public class ExpandableListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final int HEADER = 0;
public static final int CHILD = 1;
List<ContentTitle> titles;
Context context;
private List<Item> titleData = new ArrayList<Item>();
public ExpandableListAdapter(List<Item> data) {
this.titleData = data;
System.out.println("===this.titleData===" + this.titleData.size());
}
public void replaceContentFragment(String title,int id,int bookmarked) {
try {
SkillsApp SkillsApp = (SkillsApp) context.getApplicationContext();
Fragment fragment = new ContentActivityFragment();
FragmentManager fragmentManager = skillsUSAApp.mainActivity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.commit();
SkillsApp.subtitleID = id;
SkillsApp.isbookmark = (bookmarked == 0)? false:true;
SkillsApp.mainActivity.getSupportActionBar().setTitle(title);
SkillsApp.selectedSubtitleID = id;
}catch (Exception e){
e.printStackTrace();
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int type) {
View view = null;
try{
context = parent.getContext();
final SkillsApp skillsApp = (SkillsAApp)context.getApplicationContext();
if(!skillsApp.isDrawer){
switch (type) {
case HEADER:
LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.main_title, parent, false);
ListHeaderViewHolder header = new ListHeaderViewHolder(view);
return header;
case CHILD:
LayoutInflater inflater1 = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater1.inflate(R.layout.sub_title, parent, false);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d("Child", "child");
TextView text = (TextView) view.findViewById(R.id.header_title);
}
});
return new RecyclerView.ViewHolder(view) {
};
}
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
try{
System.out.println("==========##########");
final Item item = titleData.get(position);
final SkillsAApp skillsAApp = (SkillsAApp)context.getApplicationContext();
System.out.println("===onBindViewHolder item===" + item.mainTitle.title);
switch (item.type) {
case HEADER:
final ListHeaderViewHolder itemController = (ListHeaderViewHolder) holder;
itemController.refferalItem = item;
itemController.header_title.setText(item.mainTitle.title);
if (item.invisibleChildren == null) {
itemController.btn_expand_toggle.setImageResource(R.drawable.right_filled_arrow);
} else {
itemController.btn_expand_toggle.setImageResource(R.drawable.right_filled_arrow);
}
itemController.layoutItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try{
if(!skillsAApp.isDrawer){
if (item.invisibleChildren == null) {
item.invisibleChildren = new ArrayList<Item>();
int count = 0;
int pos = titleData.indexOf(itemController.refferalItem);
while (titleData.size() > pos + 1 && titleData.get(pos + 1).type == CHILD) {
item.invisibleChildren.add(titleData.remove(pos + 1));
count++;
}
notifyItemRangeRemoved(pos + 1, count);
notifyDataSetChanged();
itemController.btn_expand_toggle.setImageResource(R.drawable.right_filled_arrow);
} else {
int pos = titleData.indexOf(itemController.refferalItem);
int index = pos + 1;
for (Item i : item.invisibleChildren) {
titleData.add(index, i);
index++;
}
notifyItemRangeInserted(pos + 1, index - pos - 1);
notifyDataSetChanged();
itemController.btn_expand_toggle.setImageResource(R.drawable.down_arrow);
item.invisibleChildren = null;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
});
break;
case CHILD:
View itemTextView = (View) holder.itemView;
TextView view = (TextView) itemTextView.findViewById(R.id.header_title);
view.setText(titleData.get(position).subtitle.title);
final int pos = position;
itemTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try{
if(!skillsUSAApp.isDrawer){
TextView text = (TextView) view.findViewById(R.id.header_title);
FlurryAgent.logEvent("Sub Category Item");
replaceContentFragment(text.getText().toString(), titleData.get(pos).subtitle.subtitleId, titleData.get(pos).subtitle.bookMarked);
}
}catch (Exception e){
e.printStackTrace();
}
}
});
break;
}
}catch (Exception e){
e.printStackTrace();
}
}
#Override
public int getItemViewType(int position) {
return titleData.get(position).type;
}
#Override
public int getItemCount() {
return titleData.size();
}
#Override
public long getItemId(int position) {
return position;
}
private static class ListHeaderViewHolder extends RecyclerView.ViewHolder {
public TextView header_title;
public ImageView btn_expand_toggle;
public Item refferalItem;
public RelativeLayout layoutItem;
public ListHeaderViewHolder(View itemView) {
super(itemView);
try{
header_title = (TextView) itemView.findViewById(R.id.header_title);
btn_expand_toggle = (ImageView) itemView.findViewById(R.id.btn_expand_toggle);
layoutItem = (RelativeLayout) itemView.findViewById(R.id.ll_title);
}catch (Exception e){
e.printStackTrace();
}
}
}
public static class Item {
public int type;
public String text;
public ContentTitle mainTitle;
public ContentSubTitle subtitle;
public List<Item> invisibleChildren;
public Item(int type, String text, List<Item> children) {
this.type = type;
this.text = text;
this.invisibleChildren = children;
}
public Item(int type, ContentTitle title,ContentSubTitle stitle) {
this.type = type;
this.mainTitle = title;
this.subtitle=stitle;
}
public Item(int type, String text) {
this.type = type;
this.text = text;
}
}
}
Here is a calling adapter from tab fragment
recyclerview = (RecyclerView) v.findViewById(R.id.recyclerview);
recyclerview.setLayoutManager(new LinearLayoutManager(v.getContext(), LinearLayoutManager.VERTICAL, false));
// recyclerview.setLayoutManager(new LinearLayoutManager(v.getContext()));
ExpandableListAdapter adapter = new ExpandableListAdapter(items);
recyclerview.setAdapter(adapter);
adapter.notifyDataSetChanged();
could you please advice me what is an issue? I didn't get any console error message.Could you please help me anyone here
I want to populate a ListView with different layouts for odd and even rows. It should look like this:
I use two objects "OddListItem" and "EvenListItem" to store/access the data. I do not know how to pass both objects to my custom listview adapter and get the correct view.
My object classes:
public class OddListItem {
private String time_start;
private String time_end;
private String location;
public OddListItem(String time_start, String time_end, String location) {
super();
this.time_start = time_start;
this.time_end = time_end;
this.location = location;
}
// getters and setters
void setTimeStart(String time_start) {
this.time_start = time_start;
}
void setTimeEnd(String time_end) {
this.time_end = time_end;
}
void setLocation(String location) {
this.location = location;
}
public String getTimeStart() {
return time_start;
}
public String getTimeEnd() {
return time_end;
}
public String getLocation() {
return location;
}
}
public class EvenListItem {
private String image;
private String location;
public EvenListItem (String image, String location) {
super();
this.image = image;
this.location = location;
}
// getters and setters
void setImage(String image) {
this.image = image;
}
void setLocation(String location) {
this.location = location;
}
public String getImage() {
return image;
}
public String getLocation() {
return location;
}
}
MyCustomAdapter:
public class MyCustomAdapter extends BaseAdapter {
// Tag for Logging
private static final String TAG = "MyCustomAdapter";
int type;
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList<OddListItem> mData = new ArrayList<OddListItem>();
private LayoutInflater mInflater;
//private TreeSet mSeparatorsSet = new TreeSet();
private Context context;
public MyCustomAdapter(Context context) {
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.context = context;
}
public void addItem(final OddListItem item) {
mData.add(item);
//The notification is not necessary since the items are not added dynamically
//notifyDataSetChanged();
}
public void addSeparatorItem(final OddListItem item) {
mData.add(item);
//The notification is not necessary since the items are not added dynamically
//notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
/*if ((position%2) == 0){
type = TYPE_ITEM;
} else {
type = TYPE_SEPARATOR;
}
return type;*/
return position%2;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public OddListItem getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
Log.d(TAG, "getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
//inflate the new layout
convertView = mInflater.inflate(R.layout.detail_list_row_odd, parent, false);
holder.tv_time_from = (TextView) convertView.findViewById(R.id.tv_time_from);
holder.tv_time_to = (TextView) convertView.findViewById(R.id.tv_time_to);
holder.tv_current_location_odd = (TextView) convertView.findViewById(R.id.tv_current_location_odd);
//fill the layout with values
/*holder.tv_time_from.setText("12:34");
holder.tv_time_to.setText("12:37");
holder.tv_current_location_odd.setText("Aktueller Standort");*/
holder.tv_time_from.setText(mData.get(position).getTimeStart());
holder.tv_time_to.setText(mData.get(position).getTimeEnd());
holder.tv_current_location_odd.setText(mData.get(position).getLocation());
break;
case TYPE_SEPARATOR:
//inflate the new layout
convertView = mInflater.inflate(R.layout.detail_list_row_even, parent, false);
holder.tv_current_location_even = (TextView) convertView.findViewById(R.id.tv_current_location_even);
holder.img_transport = (ImageView) convertView.findViewById(R.id.img_transport);
//fill the layout with values
holder.tv_current_location_even.setText("Hauptbahnhof");
holder.img_transport.setImageDrawable(context.getResources().getDrawable(R.drawable.rollator));
break;
default:
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
private static class ViewHolder {
public TextView tv_time_from;
public TextView tv_time_to;
public TextView tv_current_location_odd;
public TextView tv_current_location_even;
public ImageView img_transport;
}
}
Here I generate the data and call the adapter:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detailed_connection);
generateData();
//fill ListView with custom content from MyCustomAdapter class
mAdapter = new MyCustomAdapter(getApplicationContext());
for (int i = 1; i < odd_items.size(); i++) {
mAdapter.addItem(odd_items.get(i));
if (i % 1 == 0) {
mAdapter.addSeparatorItem(odd_items.get(i));
}
}
setListAdapter(mAdapter);
//set duration text
tv_duration = (TextView)findViewById(R.id.tv_duration);
tv_duration.setText("Dauer: 22 Minuten");
}
private void generateData() {
odd_items = new ArrayList<OddListItem>();
odd_items.add(new OddListItem("12:34", "", "Aktueller Standort"));
odd_items.add(new OddListItem("12:37", "12:37", "TUM"));
odd_items.add(new OddListItem("12:42", "12:42", "Hauptbahnhof Nord"));
odd_items.add(new OddListItem("12:48", "12:48", "Hauptbahnhof"));
even_items = new ArrayList<EvenListItem>();
even_items.add(new EvenListItem("R.drawable.rollator", "3 Minuten Fußweg"));
even_items.add(new EvenListItem("R.drawable.bus", "Richtung Hauptbahnhof Nord"));
even_items.add(new EvenListItem("R.drawable.rollator", "6 Minuten Fußweg"));
mData = new Data(odd_items, even_items);
}
Any help would be great. Maybe there is also a better approach then please let me know.
I would create a Single list of Items
public class Items {
private String time_start;
private String time_end;
private String location;
private int image;
private String locationeven;
private int oddoreven;
public String getTime_start() {
return time_start;
}
public void setTime_start(String time_start) {
this.time_start = time_start;
}
public String getTime_end() {
return time_end;
}
public void setTime_end(String time_end) {
this.time_end = time_end;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public int getImage() {
return image;
}
public void setImage(int image) {
this.image = image;
}
public String getLocationeven() {
return locationeven;
}
public void setLocationeven(String locationeven) {
this.locationeven = locationeven;
}
public int getOddoreven() {
return oddoreven;
}
public void setOddoreven(int oddoreven) {
this.oddoreven = oddoreven;
}
}
In onCreate of Activity call
generateData() ;
Then
ArrayList<Items> oddorevenlist = new ArrayList<Items>();
private void generateData() {
Items item1 = new Items();
item1.setTime_start("12:34");
item1.setTime_end("");
item1.setLocation("Aktueller Standort");
item1.setOddoreven(0);
oddorevenlist.add(item1);
Items item2 = new Items();
item2.setImage(R.drawable.ic_launcher);
item2.setLocationeven("3 Minuten Fußweg");
item2.setOddoreven(1);
oddorevenlist.add(item2);
Items item3 = new Items();
item3.setTime_start("12:37");
item3.setTime_end("12:37");
item3.setLocation("Tum");
item3.setOddoreven(0);
oddorevenlist.add(item3);
Items item4 = new Items();
item4.setImage(R.drawable.ic_launcher);
item4.setLocationeven("Richtung Hauptbahnhof Nord");
item4.setOddoreven(1);
oddorevenlist.add(item4);
Items item5 = new Items();
item5.setTime_start("12:42");
item5.setTime_end("12:42");
item5.setLocation("Hauptbahnhof Nord");
item5.setOddoreven(0);
oddorevenlist.add(item5);
Items item6 = new Items();
item6.setImage(R.drawable.ic_launcher);
item6.setLocationeven("R6 Minuten Fußweg");
item6.setOddoreven(1);
oddorevenlist.add(item6);
Items item7 = new Items();
item7.setTime_start("12:48");
item7.setTime_end("12:48");
item7.setLocation("HHauptbahnhof");
item7.setOddoreven(0);
oddorevenlist.add(item7);
MyCustomAdapter mAdapter = new MyCustomAdapter(this,oddorevenlist);
setListAdapter(mAdapter);
}
Adapter code
public class MyCustomAdapter extends BaseAdapter {
// Tag for Logging
private static final String TAG = "MyCustomAdapter";
int type;
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private ArrayList<Items> oddorevenlist ;
private LayoutInflater mInflater;
private Context context;
public MyCustomAdapter(Context context, ArrayList<Items> oddorevenlist) {
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.context = context;
this.oddorevenlist = oddorevenlist;
}
#Override
public int getItemViewType(int position) {
if (oddorevenlist.get(position).getOddoreven()==0){
type = TYPE_ITEM;
} else if (oddorevenlist.get(position).getOddoreven()==1) {
type = TYPE_SEPARATOR;
}
return type;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getCount() {
return oddorevenlist.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
Log.d(TAG, "getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
//inflate the new layout
convertView = mInflater.inflate(R.layout.row_odd, parent, false);
holder.tv_time_from = (TextView) convertView.findViewById(R.id.tv_time_from);
holder.tv_time_to = (TextView) convertView.findViewById(R.id.tv_time_to);
holder.tv_current_location_odd = (TextView) convertView.findViewById(R.id.tv_current_location_odd);
holder.tv_time_from.setText(oddorevenlist.get(position).getTime_start());
holder.tv_time_to.setText(oddorevenlist.get(position).getTime_end());
holder.tv_current_location_odd.setText(oddorevenlist.get(position).getLocation());
break;
case TYPE_SEPARATOR:
//inflate the new layout
convertView = mInflater.inflate(R.layout.row_even, parent, false);
holder.tv_current_location_even = (TextView) convertView.findViewById(R.id.tv_current_location_even);
holder.img_transport = (ImageView) convertView.findViewById(R.id.img_transport);
//fill the layout with values
holder.tv_current_location_even.setText(oddorevenlist.get(position).getLocationeven());
holder.img_transport.setImageResource(R.drawable.ic_launcher);
break;
default:
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
private static class ViewHolder {
public TextView tv_time_from;
public TextView tv_time_to;
public TextView tv_current_location_odd;
public TextView tv_current_location_even;
public ImageView img_transport;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
}
Snap