Expand all list items in custom ListView (android) - android

I am using a normal ListView (mItemsList) with expandable animation (from this tutorial). It works, when I click on list item it expands and shows details for this item.
mItemsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
View details = view.findViewById(R.id.details);
// Creating the expand animation for the item
ExpandAnimation expandAni = new ExpandAnimation(details, 500);
// Start the animation on the toolbar
details.startAnimation(expandAni);
}
});
I created a showDetails button and I want to expand all list items after clicking the button, but I am completely lost. Code below doesn't work
mShowDetailsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < mItemsList.getAdapter().getCount(); i++) {
View details= v.findViewById(R.id.details);
details.startAnimation(new ExpandAnimation(details, 500));
}
}
});
Could you help me?
Here's my list_item xml file

Maybe do the similar approach like the following to automatically click item one by one to open all listciew.
mShowDetailsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < mItemsList.getAdapter().getCount(); i++) {
listView.performItemClick(
getViewByPosition(i),
i,
listView.getAdapter().getItemId(i));
}
}
});
//the listview getChildAt only return the view(item) that is visible,
//therefore add a function to get invisible view together
public View getViewByPosition(int position) {
int firstItemPosition = listView.getFirstVisiblePosition();
int lastItemPosition = firstItemPosition + listView.getChildCount() - 1;
if (position < firstItemPosition || position > lastItemPosition ) {//is invisible
return listView.getAdapter().getView(position, null, listView);
} else {
int childIndex = position - firstItemPosition;//is visible
return listView.getChildAt(childIndex);
}
}
The one you do is not work as the view is refering the mShowDetailsButton ,but not mItemsList. Thus, you cannot findViewof id R.id.details.
mShowDetailsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {//<-- this view not referring to mItemsList
}
});

Related

Save item values in recycler view object android

I am working in recycler view where I have increment and decrement buttons. My condition is that maximum I can't add 10 and minimum 0. When I am clicking on increment button of 1st row item in recycler view it is adding 1, but when I am clicking on 2nd row item in recycler view it is affecting first item of list as well. Lets say item1 becomes 1 plus.
when I am doing any increment and decrement, it should not affect other row items in RecyclerView.
int counter = 0;
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder,final int position) {
final ParseObject parseObject = arrayList.get(position);
boolean like = true, dislike = true;
if (holder instanceof MemberViewHolder) {
if (arrayList.size() > 0) {
((MemberViewHolder) holder).txtIncrement.setOnClickListener(new TextView.OnClickListener() {
#Override
public void onClick(View view) {
counter += 1;
((MemberViewHolder) holder).txtCounter.setText(counter+"");
}
});
((MemberViewHolder) holder).txtDecrement.setOnClickListener(new TextView.OnClickListener() {
#Override
public void onClick(View view) {
if(counter == 0){
}else{
counter -= 1;
((MemberViewHolder) holder).txtCounter.setText(counter+"");
}
}
});
}
}
When decrementing from item 1, it is decrementing value in row item2 as well. I want to keep the values per item.
I recommend to use a map for this.
private Map<Integer, Integer> countOfItems = new HashMap<>();
The key is the position of the item in your adapter. The value is the count of items for that position.
So inside your onBindViewHolder() you have to do some changes:
For incrementing:
int currentCount = countOfItems.get(position);
currentCount++;
countOfItems.put(position, currentCount);
For decrementing:
int currentCount = countOfItems.get(position);
if(currentCount > 0) {
currentCount--;
countOfItems.put(position, currentCount);
}
Initialize your map with count 0 for each item in the contructor of your adapter.
for(int i = 0; i < arrayList.size(); i++) {
countOfItems.put(i, 0)
}
Here is how I did it:
First create a member variable of type int[]
private int[] counter = new int[10];
Here i have given the array a default size of 10 .
Important: This will crash your app if you try to increment item above index 10. To avoid that you need to give it the size of your arrayList when you populate the arrayList (possible in the adapter constructor).
Now in your onBindViewHolder():
((MemberViewHolder) holder).txtIncrement.setOnClickListener(new TextView.OnClickListener() {
#Override
public void onClick(View view) {
counter[position] += 1;
((MemberViewHolder) holder).txtCounter.setText(counter[position]+"");
}
});
((MemberViewHolder) holder).txtDecrement.setOnClickListener(new TextView.OnClickListener() {
#Override
public void onClick(View view) {
if(counter[position] == 0){
}else{
counter[position] -= 1;
((MemberViewHolder) holder).txtCounter.setText(counter[position]+"");
}
}
});
((MemberViewHolder) holder).txtCounter.setText(counter[position]+"");
Hope this helps!

Spinner And Listview

I am using spinner and listview concurrently, I have some logic that when i scroll on list i have have a data indication that tells which values to set on spinner, and i m using
spinner.setSelection(somePosition);
and when I click on Spinner it has also some data which indicate that to set the position of
listView.setSelection(somePosition);
Problem is that when i m scrolling on listView and in my adapter i need to change the postion of spinner selected item it calls the method
spinnerSurah.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int clickPosition, long l) {
int skipTotal = 0;
for(int i = 0 ; i < clickPosition ; i++)
{
SafeJSONObject surahObject = jsonArraySurahList.getJSONObject(i);
skipTotal+= surahObject.getInt("ayas");
}
SafeJSONObject surahObject = jsonArraySurahList.getJSONObject(clickPosition);
Log.e("spinnerSurah","spinnerSurah surahObject "+surahObject.toString());
positionSelection = skipTotal;
listView.setSelection(positionSelection);
}
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
Help me, I need to just change the postion of spinner without calling its listener.
You could set a condition in your listener that bypasses the selection logic if the ListView selection is called from the listener.
Declare a boolean in your class:
boolean skip_listener = false;
and change your listener to
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int clickPosition, long l) {
if(skip_listener){skip_listener = !skip_listener;return;}
int skipTotal = 0;
for(int i = 0 ; i < clickPosition ; i++)
{
SafeJSONObject surahObject = jsonArraySurahList.getJSONObject(i);
skipTotal+= surahObject.getInt("ayas");
}
SafeJSONObject surahObject = jsonArraySurahList.getJSONObject(clickPosition);
Log.e("spinnerSurah","spinnerSurah surahObject "+surahObject.toString());
positionSelection = skipTotal;
skip_listener = true;
listView.setSelection(positionSelection);
}
}

listview getChildAt() doesn't work for imageview?

I want to use imageview like a radio button in custom listview so i used a for loop and getChildAt(position) but it doesn't work well when i scroll down it doesn't change imageview image src.
This is my code :
lvChooseReader.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, final int position, long id) {
for (int i = 0; lvChooseReader.getLastVisiblePosition() - lvChooseReader.getFirstVisiblePosition() > i; i++) {
View childView = lvChooseReader.getChildAt(i);
ImageView myImage= (ImageView) childView.findViewById(R.id.ivTest);
if (i == position) {
rr.setImageDrawable(getResources().getDrawable(R.drawable.check_mark_default));
}else {
rr.setImageDrawable(getResources().getDrawable(R.drawable.check_mark_selected));
}
}
lvChooseReader.invalidateViews();
}
});
or could any one give me a link to make radio button on item click not the radio button onclick...
lvChooseReader.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, final int position, long id) {
for (int i = lvChooseReader.getFirstVisiblePosition(); lvChooseReader.getLastVisiblePosition() > i; i++) {
View childView = lvChooseReader.getChildAt(i);
ImageView myImage= (ImageView) childView.findViewById(R.id.ivTest);
if (i == position) {
rr.setImageDrawable(getResources().getDrawable(R.drawable.check_mark_default));
}else {
rr.setImageDrawable(getResources().getDrawable(R.drawable.check_mark_selected));
}
}
lvChooseReader.invalidateViews();
The deference is:
In this code the value of i will be between first visible item to last visible item and in your case value of i was between on and total visible items.
For example:
If item 2-3-4-5 are visible i should be 1-2-3-4(position of these items in listview).
and in your case it was 0-1-2-3
i solved my problem by using static values :
i add this static variable in the dialogfragment which contain my listview
static int selectedReaderId;
and for onItemClick in listview i add this :
ChooseReader reader = chooseReaderArrayList.get(position);
selectedReaderId=reader.getReaderID();
lvChooseReader.invalidateViews();
then in the custom adapter inside my getview i add this
final ChooseReader chooseReader = readers.get(position);
if (chooseReader.getReaderID()==ChooseReaderDialog.selectedReaderId){
holder.ivTest.setImageDrawable(context.getResources().getDrawable(R.drawable.check_mark_default));
}else { holder.ivTest.setImageDrawable(context.getResources().getDrawable(R.drawable.check_mark_selected));
}

check if item is at first position from within ListView adapter during scrolling

I have a ListView. Inside the adapter, when I do the following (code below), the firstVisible is only equal to position when the list first displays. During scrolling, when the view is visibly at the top, the adapter is still not capturing it as being at the top.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
...
int firstVisible = ((ListView) parent).getFirstVisiblePosition();
if (firstVisible == position) {/
//print some stuff and do work
} else {
//print some other stuff and do other work
}
}
return rowView;
}
So my question is, how do I track when a specific item is at the top of the ListView during scrolling? And I want to do that from within the adapter.
EDIT
When the view in question reaches the top: first I want to set it to GONE so that it is not visible. In fact if I can only do that, that would be great. Then I want to grab its data for some work.
ok I think I've got a solution:
public class MyActivity extends Activity {
ListView listView;
ArrayAdapter<String> adapter;
int firstVisible;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
listView = (ListView) findViewById(R.id.listView);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
processView(v, getItem(position), true);
return v;
}
};
for (int i = 0; i < 30; i++) {
adapter.add("Value " + String.valueOf(i + 1));
}
listView.setAdapter(adapter);
firstVisible = listView.getFirstVisiblePosition();
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem != firstVisible) {
onFirstVisibleChanged(firstVisible, firstVisibleItem);
firstVisible = firstVisibleItem;
}
}
});
}
private void processView(View v, String value, boolean fromGetView) {
//if from get view we don't want to set yet wait till it comes from scrolling
if (value.contains("4") && !fromGetView) {
v.setBackgroundResource(android.R.color.holo_orange_light);
} else {
v.setBackgroundResource(android.R.color.transparent);
}
}
private void onFirstVisibleChanged(int oldIndex, int newIndex) {
View v = getViewForPosition(newIndex);
String val = adapter.getItem(newIndex);
processView(v, val, false);
}
/**
* #param position
* position of item in list
* #return null if position outside bounds
*/
public View getViewForPosition(int position) {
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount();
int wantedChild = position - firstPosition;
// Say, first visible position is 8, you want position 10, wantedChild will now be 2
// So that means your view is child #2 in the ViewGroup:
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) {
return null;
}
return listView.getChildAt(wantedChild);
}
}
the best way for me to explain what to do was just to try it myself.
what this does is make a list of strings "Value n" up to 30
if the string contains the number 4 when scrolling we will change the background color to orange. If you want the view to be removed we should be able to do that like this:
private void processView(View v, String value, boolean fromGetView) {
//if from get view we don't want to set yet wait till it comes from scrolling
if (value.contains("4") && !fromGetView) {
adapter.remove(value);
} else {
//no action needed
}
}
however this could be very confusing to the user as the moment Value 4 gets to the top it is removed and value 5 takes it's place.
getView is called before the view is visible, so when you scroll down, most of the time position will be firstVisible - 1 and when you scroll up firstVisible + totalVisibleItems.
Instead you should bind a scroll listener to your ListView
listView.setOnScrollListener(new OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// Here you can change the model of the firstView and invalidate it for her to be redrawn
}
});

Expanded listview required to expand the row one at a time

im using expanded listview in my project, i need to expand the listview only one at a time, ie i expand a item and when try to expand another item in the list the previous item which i expanded has to collapse and the new item clicked has to expand, Answers will be greatly appreciated, i'm trying with the below snippet for the on click listener..
convertViewpar.setOnClickListener(new OnClickListener() {
int i=1;
public void onClick(View v) {
i = i++;
int[] expds = new int[100];
expds[0]=0;
expds[i] = groupPosition;
if(expds[i]==expds[i-1]){
if(isExpanded)
expandlist.collapseGroup(i);
else
expandlist.expandGroup(i);
}else{
expandlist.collapseGroup(i-1);
if(isExpanded)
expandlist.collapseGroup(i);
else
expandlist.expandGroup(i);
}
}
});
Add implements OnGroupExpandListener at class level and in onCreate Method
listView.setOnGroupExpandListener(this);
and add this method
/*
* (non-Javadoc)
*
* #see
* android.widget.ExpandableListView.OnGroupExpandListener#onGroupExpand
* (int)
*/
public void onGroupExpand(int groupPosition) {
int len = expListAdapter.getGroupCount();
for (int i = 0; i < len; i++) {
if (i != groupPosition) {
listView.collapseGroup(i);
}
}
}
It will works definitely.
Try this solution. use a GroupClcik Listener and check which position is currently clicked and collpase all other groups,
expList.setOnGroupClickListener(new OnGroupClickListener() {
public boolean onGroupClick(ExpandableListView arg0, View arg1, int arg2,
long arg3) {
int count = yourAdapter.getGroupCount();
for (int i = 0; i <count ; i++)
if(arg2!=i)
exp.collapseGroup(i);
else
exp.expandGroup(i);
return false;
}
});
Or as per this solution, Programmatically collapse a group in ExpandableListView,
#Override
public void onGroupExpanded(int groupPosition){
//collapse the old expanded group, if not the same
//as new group to expand
if(groupPosition != lastExpandedGroupPosition){
accordion.collapseGroup(lastExpandedGroupPosition);
}
super.onGroupExpanded(groupPosition);
lastExpandedGroupPosition = groupPosition;
}

Categories

Resources