I am trying to set up an OnItemClickListener for the items in my Gridview. For some reason the onItemCLick method within the listener is never called.
Setting the listener and the adapter:
UsersAdapter usersAdapter = new UsersAdapter(venueUsers);
gridView.setAdapter(usersAdapter);
gridView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Intent intent = new Intent(Users.this, com.roqbot.client.login.Profile.class);
intent.putExtra("idUser", id);
startActivity(intent);
}
});
My Adapter:
private class UsersAdapter extends BaseAdapter implements ListAdapter {
private JSONArray users;
private UsersAdapter(JSONArray users) {
this.users = users;
}
public int getCount() {
return users.length();
}
public JSONObject getItem(int position) {
return users.optJSONObject(position);
}
public long getItemId(int position) {
return users.optJSONObject(position).optInt("idUser");
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = Users.this.getLayoutInflater().inflate(R.layout.user_icon, null);
JSONObject user = getItem(position);
TextView username = (TextView) convertView.findViewById(R.id.username);
username.setText(user.optString("sName"));
TextView userScore = (TextView) convertView.findViewById(R.id.userScore);
int iDJScore = user.optInt("iDJScore");
if (iDJScore > 0) {
userScore.setText(Integer.toString(iDJScore));
}
else {
userScore.setVisibility(TextView.INVISIBLE);
((ImageView) convertView.findViewById(R.id.userScoreBg)).setVisibility(View.INVISIBLE);
}
TextView userLevel = (TextView) convertView.findViewById(R.id.userLevel);
userLevel.setText(user.optString("iDJLevel"));
TextView userMatch = (TextView) convertView.findViewById(R.id.userMatch);
ImageView matchIcon = (ImageView) convertView.findViewById(R.id.matchIcon);
int iCompatibility = user.optInt("iCompatibility");
if (iCompatibility != 0) {
userMatch.setText( iCompatibility + "%");
}
else {
userMatch.setVisibility(TextView.INVISIBLE);
matchIcon.setVisibility(ImageView.INVISIBLE);
}
ImageView userIcon = (ImageView) convertView.findViewById(R.id.userIcon);
String sUserIcon = user.optString("sImageUrl-thumb");
imageLoader.DisplayImage(sUserIcon, Users.this, userIcon);
return convertView;
}
}
I am pretty baffled as to why the click listener isn't working. This code works in a lot of other places for me.
I had same problem.
In my situation, "android:focusable = true" block item click event
In My GridList Item Layout
<TextView android:id="#+id/auction_item_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
***android:focusable="true"***
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
/>
I remove [ android:focusable="true" ], problem is solved
Actually, you just need to make sure that the items in the grid aren't clickable. GridViews can't handle clickable items. Buttons for example won't work. And also if you made an item from a LinearLayout, or any other non-clickable item, you have to make sure that you didn't set the property: clickable="true".
Related
I have a listView with a custom adapter that includes text + button on each item of my list view. I'am retrieving the text from firebase without problem, but i want that if the user clicks on the button of a item, it will write on the database that that user clicked on that item.
Thank you if someone can help me, give me an idea or send a link.
I had an idea of retrieving the index(rec_1, rec_2, rec_3, etc) of the messages i'm putting on the listView and if the user clicks on the button, i write on the database index - userId : 1 or something like that, but how would i put the index value hidden on each item of the listview so i can retrieve when the button is clicked? Is just an ideia, if there is a better alternative, please tell me!
My code:
activity_recados_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/textRecados"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true" />
<Button
android:id="#+id/buttonRecadoVisto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/textRecados"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:text="Visto" />
</RelativeLayout>
RecadosCustomAdapter.java
public class RecadosCustomAdapter extends BaseAdapter implements ListAdapter {
private ArrayList<String> recadosList = new ArrayList<String>();
private Context context;
public RecadosCustomAdapter(ArrayList<String> recadosList, Context context) {
this.recadosList = recadosList;
this.context = context;
}
#Override
public int getCount() {
return recadosList.size();
}
#Override
public Object getItem(int pos) {
return recadosList.get(pos);
}
#Override
public long getItemId(int position) {
//return recadosList.get(pos).getId();
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.activity_recados_item, null);
}
//Handle TextView and display string from your list
TextView listItemText = (TextView)view.findViewById(R.id.textRecados);
listItemText.setText(recadosList.get(position));
//Handle buttons and add onClickListeners
Button buttonVisto = (Button)view.findViewById(R.id.buttonRecadoVisto);
buttonVisto.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
//do something
}
});
return view;
}
}
RecadosActivity.java
ValueEventListener valueEventListener = myRef.limitToLast(15).addValueEventListener(new ValueEventListener() {
ArrayList<String> recadosList = new ArrayList<String>();
RecadosCustomAdapter adapter = new RecadosCustomAdapter(recadosList, RecadosActivity.this);
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
recadosList.clear();
adapter.notifyDataSetChanged();
for (DataSnapshot ds : dataSnapshot.getChildren()) {
RecadosInformation rInfo = new RecadosInformation();
rInfo.setData(ds.getValue(RecadosInformation.class).getData());
rInfo.setMensagem(ds.getValue(RecadosInformation.class).getMensagem());
Log.d(TAG, "showData: Data: " + rInfo.getData());
Log.d(TAG, "showData: Mensagem: " + rInfo.getMensagem());
recadosList.add(rInfo.getData() + "\n" + rInfo.getMensagem() + "\n");
}
Collections.reverse(recadosList);
recados.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Thank you if someone can help me!
I think you should do:
FirebaseDatabase.getInstance().getReference("YOUR_NODE").child("child").setValue(yourvalue);
I think you get the idea?
Read here for more: https://firebase.google.com/docs/database/android/read-and-write
Edit you'll know inside the getView method, that method is called for each item in the list so when u click a button, use the int position to get the particular position of the item
Do:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.activity_recados_item, null);
}
//Handle TextView and display string from your list
TextView listItemText = (TextView)view.findViewById(R.id.textRecados);
listItemText.setText(recadosList.get(position));
//Handle buttons and add onClickListeners
Button buttonVisto = (Button)view.findViewById(R.id.buttonRecadoVisto);
buttonVisto.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
//upload the index which is position
}
});
return view;
}
Edit 2 give each message an id on firebase database using the push().getKey() method. So in ur getView() do:
String id = yourlist.get(position).getId();
Then do what u want with it.
My design : I have created a custom adapter(SignalsExpandableListAdapter)with a CheckedTextView for my ExpandableListView.
public class SignalsExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> listDataHandler;
private HashMap<String,List<String>> listHashMap;
public SignalsExpandableListAdapter(Context context, List<String> listDataHandler, HashMap<String, List<String>> listHashMap) {
this.context = context;
this.listDataHandler = listDataHandler;
this.listHashMap = listHashMap;
}
Then data is filled inside a fragment with HashMap and List as below. This works well. I can see children and parent elements inside my ExpandableListView.
ArrayList<List<String[]>> deviceMList = new ArrayList<>();
final List<String[]> mList = new ArrayList<>();
deviceMList.add(mList);
What I'm looking for I : When I select any child (can be multiple) I want to indicate that selection with a tick using CheckedTextView. And also I want to uncheck when I select any checked child item. (A simple check/uncheck design ). As well when any child is selected another function is called for plotting. This is where I got stuck. Every time when I select one child, random multiple children checkedTextViews are also indicated as checked not only the one I select.
After some searching I tried 3 attempts to overcome this and to check only the child I select. But it seems like neither of my attempts is working. I'm not sure what is going on. My attempts are mentioned below. I would really appreciate any suggestions on this.
I tried Attempt 4 (Described below in section II.) but still seems like check/unchecks is not happening in real-time.
Attempt 1 : Trying to make checked true inside Fragment
listAdapter = new SignalsExpandableListAdapter(context,signalsListDataHeader,signalsListHash);
signalsExpandableListView.setAdapter(listAdapter);
signalsExpandableListView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
//tickCheckboxes();
signalsExpandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
CheckedTextView sensorCheckedView = (CheckedTextView) v.findViewById(R.id.sensorsCheckedTextView);
if(!mService.mPlotManager.ifPropertyExist(deviceMList.get(groupPosition).get(childPosition))) {
sensorCheckedView.setChecked(true);
try {
if(Plot==null) {
Log.e(LOG_TAG, "Plot is null!");
}
mService.mPlotManager.addSignal(deviceMList.get(groupPosition).get(childPosition), Plot);
} catch (Exception e) {
Log.e(LOG_TAG, "Error! + e);
e.printStackTrace();
}
} else {
mService.mPlotManager.removeSignal(deviceMList.get(groupPosition).get(childPosition));
//signalsExpandableListView.setItemChecked(childPosition,false);
sensorCheckedView.setChecked(false);
}
return true;
}
});
Attempt 2 : Creating a different function and call it inside Fragment. Created function is as below and function calling is commented above Attempt 1.
//loop through groups and then children
public void tickCheckboxes() {
//CheckedTextView sensorCheckedView = (CheckedTextView) signalsExpandableListView.findViewById(R.id.sensorsCheckedTextView);
for (int i = 0; i < deviceMList.size(); i++) {
for (int j = 0; j < deviceMList.get(i).size(); j++) {
if (mService.mPlotManager.ifPropertyExist(deviceMList.get(i).get(j))) {
signalsExpandableListView.setItemChecked(j, true);
//sensorCheckedView.setChecked(true);
} else {
signalsExpandableListView.setItemChecked(j, false);
//sensorCheckedView.setChecked(false);
}
}
}
}
Attempt 3 : Accessing child element with ExpandableListView Adapter. I updated the getChildView() method as below.
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view, ViewGroup parent) {
final String childText = (String) getChild(groupPosition,childPosition);
if(view == null){
LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.sensors_list_items,null);
}
CheckedTextView txtListChild = (CheckedTextView) view.findViewById((R.id.sensorsCheckedTextView));
txtListChild.setText(childText);
txtListChild.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (txtListChild.isChecked()) {
txtListChild.setChecked(false);
} else {
txtListChild.setChecked(true);
}
}
});
return view;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
List Items xml :
<?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">
<CheckedTextView
android:id="#+id/sensorsCheckedTextView"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft"
android:textColor="#color/black"
android:paddingTop="5dp"
android:paddingBottom="5dp"/>
</LinearLayout>
Group xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/deviceNameTextView"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:text="Device Name"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:background="#color/colorAccent"
android:textColor="#color/colorPrimary"
android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"/>
</LinearLayout>
What I'm looking for II : For check/uncheck I modified Adapter as in Attempt 4 with the help of the answer mentioned below. I cannot see the checked mark in real-time. When I click a child then I want to scroll up/down to visually see the checkmark. Same as with the uncheck. It is strange. It seems like a kind of "refreshing" is required to see the check/uncheck state in real-time. I would appreciate any suggestions on how to get rid of this.
Thank you.
Attempt 4: Modified adapter. This works for a check/uncheck but can not visually see it in real-time.
public class SignalsExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> listDataHandler;
private HashMap<String,List<String>> listHashMap;
private MService mService;
private ArrayList<List<String[]>> deviceMList ;
public SignalsExpandableListAdapter(Context context, List<String> listDataHandler, HashMap<String, List<String>> listHashMap,mService service, ArrayList<List<String[]>> dMList ) {
this.context = context;
this.listDataHandler = listDataHandler;
this.listHashMap = listHashMap;
this.mService = service;
this.deviceMList =dMList;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view, ViewGroup parent) {
final String childText = (String) getChild(groupPosition,childPosition);
if(view == null){
LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.sensors_list_items,null);
}
CheckedTextView txtListChild = (CheckedTextView) view.findViewById((R.id.sensorsCheckedTextView));
txtListChild.setText(childText);
if(mService.mPlotManager.ifPropertyExist(deviceMList.get(groupPosition).get(childPosition))) {
txtListChild.setChecked(true);
} else {
txtListChild.setChecked(false);
}
return view;
}
I assume that your mService with a class named PlottingService, then try following changes to the adapter:
public class SignalsExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> listDataHandler;
private HashMap<String,List<String>> listHashMap;
private PlottingService mService;
public SignalsExpandableListAdapter(Context context, List<String> listDataHandler, HashMap<String, List<String>> listHashMap, PlottingService ps) {
this.context = context;
this.listDataHandler = listDataHandler;
this.listHashMap = listHashMap;
this.mService = ps;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view, ViewGroup parent) {
final String childText = (String) getChild(groupPosition,childPosition);
if(view == null){
LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.sensors_list_items,null);
}
CheckedTextView txtListChild = (CheckedTextView) view.findViewById((R.id.sensorsCheckedTextView));
txtListChild.setText(childText);
// Always set check state according to data.
if(mService.mPlotManager.ifPropertyExist(deviceMList.get(groupPosition).get(childPosition))) {
txtListChild.setChecked(true);
} else {
txtListChild.setChecked(false);
}
return view;
}
Inside Fragment, do Attempt 1, only change:
listAdapter = new SignalsExpandableListAdapter(context,signalsListDataHeader,signalsListHash);
to
listAdapter = new SignalsExpandableListAdapter(context,signalsListDataHeader,signalsListHash, mService);
Hope that helps!
Updated:- In Fragment, comment out the OnChildClickListener and in the adapter, use the following getChildView:
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View view, ViewGroup parent) {
String childText = (String) getChild(groupPosition,childPosition);
if(view == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.sensors_list_items,null);
}
CheckedTextView txtListChild = (CheckedTextView) view.findViewById((R.id.sensorsCheckedTextView));
txtListChild.setText(childText);
// Always set check state according to data.
if(mService.mPlotManager.ifPropertyExist(deviceMList.get(groupPosition).get(childPosition))) {
txtListChild.setChecked(true);
} else {
txtListChild.setChecked(false);
}
txtListChild.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckedTextView sensorCheckedView = (CheckedTextView)v;
if(!sensorCheckedView.isChecked()) {
sensorCheckedView.setChecked(true);
try {
if(Plot==null) {
Log.e(LOG_TAG, "Plot is null!");
}
mService.mPlotManager.addSignal(deviceMList.get(groupPosition).get(childPosition), Plot);
} catch (Exception e) {
Log.e(LOG_TAG, "Error!" + e);
e.printStackTrace();
}
} else {
mService.mPlotManager.removeSignal(deviceMList.get(groupPosition).get(childPosition));
sensorCheckedView.setChecked(false);
}
}
});
return view;
}
Updated 2:- In Fragment, comment out the OnChildClickListener and in the adapter, add a inner class and use the following getChildView:
class Position {
int group, child;
Position(int group, int child) {
this.group = group;
this.child = child;
}
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view, ViewGroup parent) {
String childText = (String) getChild(groupPosition,childPosition);
if(view == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.sensors_list_items,null);
}
CheckedTextView txtListChild = (CheckedTextView) view.findViewById((R.id.sensorsCheckedTextView));
txtListChild.setText(childText);
// Always set check state according to data.
if(mService.mPlotManager.ifPropertyExist(deviceMList.get(groupPosition).get(childPosition))) {
txtListChild.setChecked(true);
} else {
txtListChild.setChecked(false);
}
txtListChild.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckedTextView sensorCheckedView = (CheckedTextView)v;
int groupPosition = ((Position)v.getTag()).group;
int childPosition = ((Position)v.getTag()).child;
if(!sensorCheckedView.isChecked()) {
sensorCheckedView.setChecked(true);
try {
if(Plot==null) {
Log.e(LOG_TAG, "Plot is null!");
}
mService.mPlotManager.addSignal(deviceMList.get(groupPosition).get(childPosition), Plot);
} catch (Exception e) {
Log.e(LOG_TAG, "Error!" + e);
e.printStackTrace();
}
} else {
mService.mPlotManager.removeSignal(deviceMList.get(groupPosition).get(childPosition));
sensorCheckedView.setChecked(false);
}
}
});
txtListChild.setTag(new Position(groupPosition, childPosition));
return view;
}
If Updated 2 still have the issue of multiple checked items, then the possible cause is mService.mPlotManager.ifPropertyExist(deviceMList.get(groupPosition).get(childPosition)). Instead of using mService to verify if an item is selected or not, it may be a better idea to change listHashMap from HashMap<String, List<String>> to HashMap<String, List<ChildItem>> [The accepted answer in Values of counter changes after scrolling ExpendableListView, you need a boolean field instead of the integer field, quantity]. Then when a child item is clicked, check and update with the list.
Hey Guys I am working right now on a University project and have some problems which I found out randomly. Actually, I have to create an app (android) for an upcoming event where the user can see all the events in an overview and can tag his favorite ones.
I have a listview object, which is displaying all the items from a List<>
I wanna give the opportunity that the user can tag his favorite events which shall appear in a new fragment but I have problems with the changing icon. When you tag the first item in the list, it also tags every fourth item in the list additionally. I don't know why and it would be great if you can help! :)
the selector for the Image View
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="#drawable/ic_bookmark_black_24dp_copy_3" />
<item android:state_selected="false" android:drawable="#drawable/ic_bookmark_border_black_24dp_copy_3" />
<item android:drawable="#drawable/ic_bookmark_black_24dp_copy_3" />
</selector>
the adapter including the activating function to change the icon
public class CustomArrayAdapter extends BaseAdapter{
private List<EventItem> listData;
private LayoutInflater layoutInflater;
private Context context;
static class ViewHolder {
TextView titleView;
TextView descriptionView;
TextView authorView;
TextView reportedDateView;
TextView locationView;
ImageView favorite;
}
public CustomArrayAdapter(Context context, List<EventItem> listData) {
this.context = context;
this.listData = listData;
Collections.sort(listData);
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_event_item, null);
holder = new ViewHolder();
holder.titleView = (TextView) convertView.findViewById(R.id.title);
holder.authorView = (TextView) convertView.findViewById(R.id.author);
holder.descriptionView = (TextView) convertView.findViewById(R.id.description);
holder.locationView = (TextView) convertView.findViewById(R.id.location);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.time);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.titleView.setText(listData.get(position).getTitle());
holder.authorView.setText(listData.get(position).getAuthor());
holder.descriptionView.setText(listData.get(position).getDescription());
holder.locationView.setText(listData.get(position).getLocation());
holder.reportedDateView.setText(getTime(position));
holder.favorite = (ImageView) convertView.findViewById(R.id.bookmark);
holder.favorite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(view.isSelected()) {
System.out.println("Position: ");
view.setSelected(false);
}else{
view.setSelected(true);
}
}
});
return convertView;
}
private String getTime(int position) {
Date start = listData.get(position).getStartTime();
Date end = listData.get(position).getEndTime();
String startTime = start.toString();
String endTime = end.toString();
return String.format("%1s%2s%3s", start.toString().substring(11, 19), " - ", end.toString().substring(11, 19));
}
}
And here my Image view out of the xml file where all the other views where styled
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/description"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginEnd="8dp"
android:src="#drawable/bookmark_icon_selector"
android:tint="#color/colorDhdPrimary"
android:id="#+id/bookmark"
/>
and here the list view in the separate XML.
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:id="#+id/list_container">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/list_event"
app:layout_constraintBottom_toBottomOf="#+id/list_container"
app:layout_constraintLeft_toLeftOf="#+id/list_container"
app:layout_constraintRight_toRightOf="#+id/list_container"
app:layout_constraintTop_toTopOf="#+id/list_container"
/>
Solution can be multiple . One way to do this is just add a boolean in your EventItem POJO.
class EventItem{
boolean isSelected;
}
Now toggle this boolean onClick.
final int pos=position;
holder.favorite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listData.get(pos).isSelected=!listData.get(posi).isSelected;
notifyDataSetChanged();
}
});
And in onBindViewHolder just check for boolean.
if(listData.get(position).isSelected){
holder.favorite.setSelected(true);
}else{
holder.favorite.setSelected(false);
}
Android recycles list items for performance purposes. It is highly recommended to reuse them if you want your ListView to scroll smoothly. So if you check once and scroll, then other views reuse these views and gets checked.
So in getView change code like this
holder.favorite = (ImageView) convertView.findViewById(R.id.bookmark);
if(checkCondition){
holder.favorite.setSelected(true);
}else{
holder.favorite.setSelected(false);
}
holder.favorite.setOnClickListener(new View.OnClickListener() {
....
....
I have the same problem and this answer by
Thoriya Prahalad helps.
override this method in your adapter class.
#Override
public int getItemViewType(int position) {
return position;
}
I am trying to create a custom listview like this: http://i.stack.imgur.com/l8ZOc.png
Currently I managed to create it but there is a problem. For example when there are 8 items, it loads the first 4, then loads the remiaining items as you scroll down. When scrolling down, it works fine.
However, when scrolling back up from bottom, at the middle of list, it instantly moves to top, skipping 2-3-4. items. Then you can scroll down normally again, but when scrolling up, it instantly goes to top of the list.
How can i prevent this from happening?
Here is my code:
public class MyActivity extends Activity implements AdapterView.OnItemClickListener {
String headers[];
String image_urls[];
List<MyMenuItem> menuItems;
ListView mylistview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
menuItems = new ArrayList<MyMenuItem>();
headers = getResources().getStringArray(R.array.header_names);
image_urls = getResources().getStringArray(R.array.image_urls);
for (int i = 0; i < headers.length; i++) {
MyMenuItem item = new MyMenuItem(headers[i], image_urls[i]);
menuItems.add(item);
}
mylistview = (ListView) findViewById(R.id.list);
MenuAdapter adapter = new MenuAdapter(this, menuItems);
mylistview.setAdapter(adapter);
mylistview.setOnItemClickListener(this);
}
}
public class MyMenuItem {
private String item_header;
private String item_image_url;
public MyMenuItem(String item_header, String item_image_url){
this.item_header=item_header;
this.item_image_url=item_image_url;
}
public String getItem_header(){
return item_header;
}
public void setItem_header(String item_header){
this.item_header=item_header;
}
public String getItem_image_url(){
return item_image_url;
}
public void setItem_image_url(String item_image_url){
this.item_image_url=item_image_url;
}
}
public class MenuAdapter extends BaseAdapter{
Context context;
List<MyMenuItem> menuItems;
MenuAdapter(Context context, List<MyMenuItem> menuItems) {
this.context = context;
this.menuItems = menuItems;
}
#Override
public int getCount() {
return menuItems.size();
}
#Override
public Object getItem(int position) {
return menuItems.get(position);
}
#Override
public long getItemId(int position) {
return menuItems.indexOf(getItem(position));
}
private class ViewHolder {
ImageView ivMenu;
TextView tvMenuHeader;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.menu_item, null);
holder = new ViewHolder();
holder.tvMenuHeader = (TextView) convertView.findViewById(R.id.tvMenuHeader);
holder.ivMenu = (ImageView) convertView.findViewById(R.id.ivMenuItem);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
MyMenuItem row_pos = menuItems.get(position);
Picasso.with(context)
.load(row_pos.getItem_image_url())
// .placeholder(R.drawable.empty)
// .error(R.drawable.error)
.into(holder.ivMenu);
holder.tvMenuHeader.setText(row_pos.getItem_header());
Log.e("Test", "headers:" + row_pos.getItem_header());
return convertView;
}
}
<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="match_parent"
tools:context=".MyActivity">
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
Use lazy loading mechanism to load your image data.
There is one nice example here
I have made an Listview populated with list_row_layout.xml(which is populated with json serializable class), i have clickable textview and onclick changing text from "Accept" to "Accepted". But when i click it on first listview item, another textview listview items below are changing. Here's some photos to descibe you better
Activity class
feedListView.setAdapter(new CustomListAdapter(this, feedList));
adapter class
public class CustomListAdapter extends BaseAdapter
{
private ArrayList<FeedItem> listData;
private LayoutInflater layoutInflater;
private Context mContext;
public CustomListAdapter(Context context, ArrayList<FeedItem> listData)
{
this.listData = listData;
layoutInflater = LayoutInflater.from(context);
mContext = context;
}
#Override
public int getCount()
{
return listData.size();
}
#Override
public Object getItem(int position)
{
return listData.get(position);
}
#Override
public long getItemId(int position)
{
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
if (convertView == null)
{
convertView = layoutInflater.inflate(R.layout.list_row_layout, null);
holder = new ViewHolder();
holder.headlineView = (TextView)convertView.findViewById(R.id.title);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.confid);
holder.approve = (TextView) convertView.findViewById(R.id.approveTV);
holder.approve.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View argView)
{
holder.approve.setText("accepted");
}
}
);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
FeedItem newsItem = listData.get(position);
holder.headlineView.setText(Html.fromHtml(newsItem.getTitle()));
holder.reportedDateView.setText(Html.fromHtml(newsItem.getContent()));
holder.approve.setTag(newsItem);
return convertView;
}
static class ViewHolder
{
TextView approve;
TextView headlineView;
TextView reportedDateView;
ImageView imageView;
}
}
textview code
<TextView
android:id="#id/approveTV"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="5dp"
android:background="#drawable/pressed"
android:gravity="fill"
android:text="Accept"
android:clickable="true"
android:textColor="#0D98BA"
android:textSize="17sp" />
You have to write some tracking position functionality which remember the position which you have changed and make sure that only text of position changed .
you must set id to each row, and save it in one array,like integer and when you click on one row you must change the value of that, and in changing text or anything you must check the value of that row,if 0 then set default and if 1 then so what you want: my idea is create int[] with length of that is size of your list,
first you must define you int[] like below and set to zero every index.
int[] selected = new int[listData.getsize()]
something like this in getview:
holder.approve.setId(Html.fromHtml(newsItem.getId());
and after else statement in getView:
if (selected[position] == 0)
{
// set default
}
else
{
// any changing that you want
}
and in onClick:
selected[holder.approve.getId()] = 1;
// any change that you want
Try the below code:-
public View getView(final int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
if (convertView == null)
{
holder = new ViewHolder();
convertView = layoutInflater.inflate(R.layout.list_row_layout, null);
holder.headlineView = (TextView)convertView.findViewById(R.id.title);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.confid);
holder.approve = (TextView) convertView.findViewById(R.id.approveTV);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
FeedItem newsItem = listData.get(position);
holder.headlineView.setText(Html.fromHtml(newsItem.getTitle()));
holder.reportedDateView.setText(Html.fromHtml(newsItem.getContent()));
holder.approve.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View argView)
{
holder.approve.setText("accepted");
}
}
);
return convertView;
}
Thanks!!