I have list with only three items , and i'm using GridLayout with two columns , so when calling it i found that rwo two has only one item , and the last is my footer , so i want to something add empty item or move my footer when my list has odd numbers to move new row
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
if (holder instanceof FooterViewHolder) {
loadChatMessages();
}
private boolean isPositionFooter(int position) {
return position == dish.size();
}
#Override
public int getItemViewType(int position) {
if (isPositionFooter(position)) {
return TYPE_FOOTER;
}
return TYPE_ITEM;
}
#Override
public int getItemCount() {
return dish.size() + 1;
}
You should implement your own version of GridLayoutManager.SpanSizeLookup and add it to your layout manager by calling gridlayoutManager.setSpanSizeLookup(myLookup).
The description of SpanSizeLookup reads
A helper class to provide the number of spans each item occupies.
So for every normal item you'd return 1 (column used) and in case of your footer you need to return 2 (or the amount of columns total) from getSpanSize(int position) and you're set.
This will signal the layout manager that it needs the whole row.
Related
i have the following code. If the name of the checkbox is in the 'deneme' array that the function takes, I want the checkbox to be checked. but those that don't enter the 'if' are marked strangely. and there are random checked when scrolling up and down
public SubjectRecyclerViewAdapter(ArrayList<Subject> subjects, ArrayList<String> deneme) {
this.subjects = subjects;
this.deneme = deneme;
}
#Override
public void onBindViewHolder(#NonNull SubjectRecyclerViewAdapter.MyViewHolder holder, int position) {
holder.checkBox.setText(subjects.get(position).getCheckBoxSubject());
if (deneme.contains(subjects.get(position).getCheckBoxSubject())) {
holder.checkBox.setChecked(true);
}}
Because the ViewHolders are recycled (meaning they are reused as you scroll) you need to explicitly set the checkbox's state either way (so that it changes whatever previous state the ViewHolder had):
if (deneme.contains(subjects.get(position).getCheckBoxSubject())) {
holder.checkBox.setChecked(true);
} else {
holder.checkBox.setChecked(false);
}
In case any 1 find this problem, I hope this helps some1 in the future. I wanted to share the final solution because I think it helps more than the code I started with and couldn't get any answer which led to this solution.
This was a reference for my solution:
How can I select only one checkbox in Recyclerview and notifydataset changed
I'm only sharing crucial parts of the code, which affect directly to the radio button selection problem.
this was my solution:
public class NewGameCourseAdapter extends RecyclerView.Adapter<NewGameCourseAdapter.NewGameCourseViewHolder> {
private int selectedPosition = -1;// no selection by default
#Override
public void onBindViewHolder(#NonNull final NewGameCourseViewHolder holder, final int position) {
/** This can prevent some unwanted actions in some cases **/
holder.mRadioButton.setOnCheckedChangeListener(null);
holder.mRadioButton.setChecked(selectedPosition == position);
holder.mRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
selectedPosition = holder.getAdapterPosition();
if (selectedPosition == position) {
holder.mRadioButton.setChecked(true);
notifyDataSetChanged();
} else {
holder.mRadioButton.setChecked(false);
notifyDataSetChanged();
}
}
});
I am trying to change background color in specific item(s) in a RecycleView.
Because I need to set text too, I have the following code that works fine:
protected void populateViewHolder(RankingViewHolder viewHolder, final Ranking model, int position)
{
final Context mContext = getActivity().getApplicationContext();
viewHolder.txt_name.setText(model.getUserName());
viewHolder.txt_score.setText(String.valueOf(model.getScore()));
viewHolder.txt_class.setText(model.getUser_class());
Picasso.with(mContext).load(model.getAvatarUrl()).error(R.drawable.ic_people_black_24dp).into(viewHolder.personPhoto);
int totalRanking = adapter.getItemCount();
int realRank = totalRanking - viewHolder.getAdapterPosition();
viewHolder.ranknumber.setText("# "+String.valueOf(realRank));
}
This works as I want and realRanktakes the correct values, and the viewHolder.ranknumber.setText("# "+String.valueOf(realRank));
Sets the right text with no problem.
Now I am trying (as I got a number/text result correct, to make an if statement like this:
if(adapter.getItemCount() -viewHolder.getAdapterPosition() == 0)
{
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
if(adapter.getItemCount() -viewHolder.getAdapterPosition() == 1)
{
viewHolder.itemView.setBackgroundColor(Color.YELLOW);
}
if(adapter.getItemCount() -viewHolder.getAdapterPosition() == 2)
{
viewHolder.itemView.setBackgroundColor(Color.BLUE);
}
(I tried with String.valueOf(realRank)equality, with realRankequality too)
In all cases I have the same result. The color changes as its should at positions 1,2,3 BUT it changes at positions 7,8,9 and 14,15,16 and 21,22,23 etc.
What am I missing here?
public class RankingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
private ItemClickListener itemClickListener;
public TextView txt_name, txt_score, txt_class, ranknumber;
public ImageView personPhoto;
public RankingViewHolder(View itemView)
{
super(itemView);
txt_name = itemView.findViewById(R.id.txt_name);
txt_score = itemView.findViewById(R.id.txt_score);
personPhoto = itemView.findViewById(R.id.person_photo);
txt_class = itemView.findViewById(R.id.txt_class);
ranknumber = itemView.findViewById(R.id.ranknumber);
itemView.setOnClickListener(this);
}
public void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
#Override
public void onClick(View view) {
itemClickListener.onClick(view , getAdapterPosition(),false);
}
}
The adapter:
adapter = new FirebaseRecyclerAdapter<Ranking, RankingViewHolder>(
Ranking.class,
R.layout.layout_ranking,
RankingViewHolder.class,
rankingTbl.orderByChild("score").limitToFirst(100)
)
This line of code int realRank = totalRanking - viewHolder.getAdapterPosition();gives a number (1,2,3,4,5,6 etc.) Why i cannot use this number to check equality?
Notice
Keeping this code for NOT working solution, just for future reference:
if(position == 0){
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
else if(position == 1){
viewHolder.itemView.setBackgroundColor(Color.YELLOW);
}
else if(position == 2){
viewHolder.itemView.setBackgroundColor(Color.BLUE);
}
else{
viewHolder.itemView.setBackgroundColor(Color.WHITE);
}
This changes the color BUT not for only 3 first items. As you scroll down, changes the color for every 3 first viewable items like before, meaning 1,2,3, 7,8,9, etc.
Update:
I dont use a custom adapter, i use FirebaseRecyclerAdapter.
Thanks to #Muhammad Haroon comment i checked that has getItemViewType. So now i m trying with it like
position =adapter.getItemViewType( 0);
if(position == 0){
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
Not working for now, but i think its the correct direction...
Update 2
With position its not possible as RecycleView recycles the views so i have the same result. The working code is
if (linearLayoutManager.findFirstVisibleItemPosition() > 0) {
viewHolder.itemView.setBackgroundResource(R.drawable.blackframe);
}
else{
viewHolder.itemView.setBackgroundResource(R.drawable.goldframe);
}
Works fine except that after scrolling loosing the change of background.
So as we want and need the perfection, any idea for keeping even after scroll?
hi try add this in your Adapater it may solve your problem.
#Override
public int getItemViewType(int position) {
return position;
}
Please give this a try
override in your custom adapter
#Override
public long getItemId(int position) {
return position;
}
and in in your adapter object:
myAdapter.setHasStableIds(true);
In populateViewHolder add these line of code
if(position == 0){
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
else if(position == 1){
viewHolder.itemView.setBackgroundColor(Color.YELLOW);
}
else if(position == 2){
viewHolder.itemView.setBackgroundColor(Color.BLUE);
}
else{
viewHolder.itemView.setBackgroundColor(Color.WHITE);
}
position is a parameter in populateViewHolder.
How to remove ListView items from ListView on Android?
But, I want to set a click on each item to 3 before removing it.
So if the item at the first position is clicked once and the second item clicked twice, do not remove any item until the first item click reaches 3. Then remove that item only and for other items in the ListView, each has to be clicked 3 times.
listi.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,final int position, long id) {
final PopupMenu pop = new PopupMenu(Danger.this, listi);
pop.getMenuInflater().inflate(R.menu.menu_location, pop.getMenu());
pop.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.Remove:
items.remove(position);
}//swithc
return false;
Create an ArrayList of integers and initialize it with exactly with same element count of your list view and set value of all elements of the list = 0
ArrayList<integers> counterList = new Arraylist();
for(int i = 0; i < listi.getAdapter.getChildrenCount(); i++){ // get total elements in adapter
counterList.add(0); // set each element of array list to 0
}
Then here:
listi.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,final int position, long id) {
final PopupMenu pop = new PopupMenu(Danger.this, listi);
pop.getMenuInflater().inflate(R.menu.menu_location, pop.getMenu());
pop.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.Remove:
if(counterList.get(position) >= 2){
items.remove(position); // remove current position item from arraylist adapter and notify data set changed
counterList.remove(position); // remove the current position element from counter list too
} else {
counterList.set(position, counterList.get(position) + 1); // if 3 clicks have not happened then increase the counter.
}
}//swithc
return false;
Use static variable and hold it with null,Include the static variable inside ClickListener , Once the variable reaches 3,you can remove the items from list view
I would suggest adding 2 fields: int timesClicked and int lastItemId, then in your onMenuItemClick method, check if the Item needs to be removed:
int timesClicked = 0;
int lastItemId;
...
#Override
public boolean onMenuItemClick(MenuItem item) {
if(item.getItemId() == lastItemId) {
if(timesClicked == 3) {
timesCliked == 0;
items.remove(item);
} else timesClicked++;
} else {
lastItemId = item.getItemId();
timesClicked = 0;
}
}
This should work.
Make a bean (Model) class for having record of clicked item according to
their corresponding position and every time on item clicked first check that
how many time this item is clicked if it's returning 2 then remove the item
else not.
I am using a custom expandable list adapter. I highlight a child when the user clicks on it. This works fine until the user opens/collapses a group. Say the user touches Group 2 Item 1. This highlights Group 2 Item 1. Then the user opens Group 1. Now Group 3 Item 2 is highlighted. I have done some testing choosing different items and I can not find a pattern where the highlighted row will jump to. Sometimes its up in the list, sometimes its down. I'm having trouble figuring out the logic to put in my activity's onGroupExpandListener and onGroupCollapseListener to rehighlight the correct view. Any ideas?
EDIT: Current code inside my onChildClickListener
if (groupPosition == 0){
switch(childPosition) {
case 0:
previouslySelectedView.setBackgroundResource(R.color.transparent);
currentlySelectedView.setBackgroundResource(R.color.blue);
break;
Same code for all the groups/children
Item slection in ExpandableListView is made through flat list (absolute positiond). Thus if the newlly opened group is before the currenet selection and has fewer children then the selection will move up and vice versa. I suggest to set choice mode to none and implement onclick/expand logic to handle focus on your own - implement tags for views, for example, and set the currently highlighted item via the tag.
Here are few suggestions:
In the ExpandableListView.OnChildClickListener first you perform ExpandableListView.findViewWithTag(theTag) to check for views with such tag and unmark them (also setTag(null)) and restore the background. Then for the item clicked setTag(theTag) and change the background to selected. Of course you can have some other logic and have multiple items marked. Note that once the view is destroyed you will lose the selection (for example during expands).
Have some custom map or something that will hold a unique ID of the view and the (un)marked state. That's the best solution that will allow to maintain persistent selection across scrolls and expands.
In the backing adapter introduce a "marked" state. Thus the marking will be persistent even between application start/stop. Not a good approach, though, because selection is more of a UI behaviour.
I am currently doing an ExpandableListView selection with Choice Mode Multiple of the list. But since, as I said, the selection is per position I had to sacrifice in terms of functionality - namely, I clear the selection whenever a manipulation is made. The previous implementation was with custom Map holding the selected IDs and - to honest - it was the better approach.
This is how I get selected IDs (remember I use choice mode multiple):
final SparseBooleanArray checkedPositions = expList.getCheckedItemPositions();
final ExpandableListAdapter adapter = expList.getExpandableListAdapter();
List<Long> checkedIds = new ArrayList<Long>();
if (packedPositionType == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
for (int i = checkedPositions.size() - 1; i >= 0; i--) {
if (checkedPositions.valueAt(i)) {
checkedIds.add(adapter.getGroupId(checkedPositions.keyAt(i)));
}
}
}
In your case, though, you will want to check for CHILD packed positions. Also note that my adapter has stable (unique) ids. If you do not have stable IDs then you can rely on ExpandableListView's getPackedPositionForChild() method and store the packed position as marked.
Right way to do it (Will solve jumping highlight upon group collapse)
Do the following on ExpandableListView:
Step 1. Set choice mode to single (Can be done in xml as android:choiceMode = "singleChoice")
Step 2. Use a selector xml as background (android:listSelector = "#drawable/selector_list_item")
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="#android:integer/config_mediumAnimTime">
<item android:drawable="#android:color/holo_blue_bright" android:state_pressed="true"/>
<item android:drawable="#android:color/holo_blue_light" android:state_selected="true"/>
<item android:drawable="#android:color/holo_blue_dark" android:state_activated="true"/>
</selector>
Step 3. Call expandableListView.setItemChecked(index,true) in onChildClick() callback.
index is a 0 based index of the child item calculated as follows
Group 1 [index = 0]
Child item 1
Child item 2
Child item 3 [index = 3]
Group 2 [index = 4]
Child item 1
Child item 2
Child item 3 [index = 7]
Group 3 [index = 8]
Child item 1
Child item 2
Child item 3 [index = 11]
If we have list headers as well, they would also account for index values.
Here is a working example:
#Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
...
int index = parent.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition));
parent.setItemChecked(index, true);
return true;
}
My solution for the collapse issue :
mDrawerExpandableList.setOnGroupCollapseListener(new OnGroupCollapseListener() {
#Override
public void onGroupCollapse(int groupPosition) {
if(ExpandableListView.getPackedPositionGroup(selectedFragmentId) == groupPosition) {
mDrawerExpandableList.setItemChecked(mDrawerExpandableList.getFlatListPosition(ExpandableListView.getPackedPositionForGroup(groupPosition)), true);
}
}
});
mDrawerExpandableList.setOnGroupExpandListener(new OnGroupExpandListener() {
#Override
public void onGroupExpand(int groupPosition) {
if(ExpandableListView.getPackedPositionGroup(selectedFragmentId) == groupPosition) {
mDrawerExpandableList.setItemChecked(((ExpandableListView)drawerListView).getFlatListPosition(selectedFragmentId), true);
}
}
});
//MY LIST A FOLLOWS
(0)SALES
(0)SALES
(1)SALES VIEW
(2)SALES RETURN
(3)SALES RETURN VIEW
(1)STOCK
(0)ADD STOCK
(1)VIEW STOCK
(2)SETTINGS
(3)NOTIFICATION
//declare tow integer variable globali as follows
private int lastCheckedGroupPosition=-1;
private int lastCheckedChildPosition=-1;
mDrawerList.setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
if(groupPosition==2){
lastCheckedGroupPosition=groupPosition;
lastCheckedChildPosition=-1;
int index = parent.getFlatListPosition(ExpandableListView.getPackedPositionForGroup(groupPosition));
parent.setItemChecked(index, true);
//TODO Write here the code for opening settings page
...............
...............
...............
return true;
}
else if(groupPosition==3){
lastCheckedGroupPosition=groupPosition;
lastCheckedChildPosition=-1;
int index = parent.getFlatListPosition(ExpandableListView.getPackedPositionForGroup(groupPosition));
parent.setItemChecked(index, true);
//TODO Write here the code for opening settings page
...............
...............
...............
return true;
}
return false;
}
});
mDrawerList.setOnChildClickListener(new OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
if(groupPosition==0){
if(childPosition==0){
//TODO Write here the code for opening SALES page
...............
...............
...............
}
else if(childPosition==1){
//TODO Write here the code for opening SALES VIEW page
...............
...............
...............
}
else if(childPosition==2){
//TODO Write here the code for opening SALES RETURN page
...............
...............
...............
}
else if(childPosition==3){
//TODO Write here the code for opening SALES RETURN VIEW page
...............
...............
...............
}
}
else if(groupPosition==1){
if(childPosition==0){
//TODO Write here the code for opening ADD STOCK page
...............
...............
...............
}
else if(childPosition==1){
//TODO Write here the code for opening VIEW STOCK page
...............
...............
...............
}
}
int index = parent.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition));
parent.setItemChecked(index, true);
lastCheckedGroupPosition=groupPosition;
lastCheckedChildPosition=childPosition;
return false;
}
});
mDrawerList.setOnGroupExpandListener(new OnGroupExpandListener() {
#Override
public void onGroupExpand(int groupPosition) {
if(groupPosition==lastCheckedGroupPosition){
if(lastCheckedChildPosition!=-1){
int index = mDrawerList.getFlatListPosition(ExpandableListView.getPackedPositionForChild(lastCheckedGroupPosition, lastCheckedChildPosition));
mDrawerList.setItemChecked(index, true);
}
else{
int index = mDrawerList.getFlatListPosition(ExpandableListView.getPackedPositionForGroup(lastCheckedGroupPosition));
mDrawerList.setItemChecked(index, true);
}
}
else{
if(mDrawerList.isGroupExpanded(lastCheckedGroupPosition)){
if(lastCheckedChildPosition!=-1){
int index = mDrawerList.getFlatListPosition(ExpandableListView.getPackedPositionForChild(lastCheckedGroupPosition, lastCheckedChildPosition));
mDrawerList.setItemChecked(index, true);
}
else{
int index = mDrawerList.getFlatListPosition(ExpandableListView.getPackedPositionForGroup(lastCheckedGroupPosition));
mDrawerList.setItemChecked(index, true);
}
}
else{
mDrawerList.setItemChecked(-1, true);
}
}
}
});
mDrawerList.setOnGroupCollapseListener(new OnGroupCollapseListener() {
#Override
public void onGroupCollapse(int groupPosition) {
if(groupPosition==lastCheckedGroupPosition){
if(lastCheckedGroupPosition!=-1){
int index = mDrawerList.getFlatListPosition(ExpandableListView.getPackedPositionForGroup(lastCheckedGroupPosition));
mDrawerList.setItemChecked(index, true);
}
else{
mDrawerList.setItemChecked(-1, true);
}
}
if(mDrawerList.isGroupExpanded(lastCheckedGroupPosition)){
if(lastCheckedChildPosition!=-1){
int index = mDrawerList.getFlatListPosition(ExpandableListView.getPackedPositionForChild(lastCheckedGroupPosition, lastCheckedChildPosition));
mDrawerList.setItemChecked(index, true);
}
else{
int index = mDrawerList.getFlatListPosition(ExpandableListView.getPackedPositionForGroup(lastCheckedGroupPosition));
mDrawerList.setItemChecked(index, true);
}
}
else{
mDrawerList.setItemChecked(-1, true);
}
}
});