I want to draw a check mark for the image view I click on and uncheck the imageview I clicked on before using the following code snip. I store last checked position in mDeviceAdapter. When I try to uncheck old position, the image view always gives null even for the partial visible image view. I am really confused because I thought only invisible one is recycled... Newbie in Android and any comment is appreciated.
public void CheckableImageView#setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
invalidate();
}
}
mDeviceGallery.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
CheckableImageView viewToCheck = (CheckableImageView) view;
if (!viewToCheck.isChecked()) {
int oldCheckedPosition = mDeviceAdapter
.getCheckedPosition();
mDeviceAdapter.setCheckedPosition(position);
View checkedView = mDeviceGallery
.getChildAt(oldCheckedPosition);
Log.d(TAG, "old position="+oldCheckedPosition + "old view="+checkedView);
if (checkedView != null) {
((CheckableImageView) checkedView)
.setChecked(false);
Log.d(TAG, "uncheck position="
+ oldCheckedPosition);
}
viewToCheck.setChecked(true);
That's not the right approach.
You need to add to your data type a boolean field (i.e mIsChecked).
On the onItemClick method set the value of that variable to true and keep its INDEX as a member of the adapter. When another item is clicked set the value of that item to true and set the value of the saved one to false (change the value of the datatype in you ArrayList in the INDEX you stored in the previous click).
Now, in the getView() method, you must have if/else statement. Something like:
if (item.isChecked())
{
checkedView.setChecked(true);
}
else
{
checkedView.setChecked(false);
}
Example to the onClick method: (just a general direction)
if (item.isChecked())
{
checkedView.setChecked(false);
yourList.get(position).setChecked(true);
yourList.get(mLastCheckedIndex).setChecked(false);
mLastCheckedIndex = position;
notifyDataSetChanged();
}
else
{
//same but opposite.
}
Hope this helps!
Related
I have created a horizontal recyclerview list. below is the image I have attached.
problem is that I have to change bulb state when everytime user clicked that row from off state to on state and on state to off state.
How do I implement this logic? please help me to find out the solution.
i want to change light color according to user clicks, if he clicks on then it should change its color for that row and vise versa
public void onClick(View view, int position) {
//toast("clicked" + position );
if (!lightClicked){
ImageView lightPopUp = view.findViewById(R.id.row_light_thumbnail);
DrawableCompat.setTint(lightPopUp.getDrawable().mutate(), ContextCompat.getColor(getContext(), R.color.white));
//toast("light on");
lightClicked = true;
}else {
ImageView lightPopUp = view.findViewById(R.id.row_light_thumbnail);
//toast("light off");
DrawableCompat.setTint(lightPopUp.getDrawable().mutate(), ContextCompat.getColor(getContext(), R.color.colorAccent));
lightClicked = false;
}
//View view1 = mLayoutManager.findViewByPosition(position);
}
Dont directly do this change as the recycler view's cells are reused and it wont work as expected, so instead apply the change in the list you are using. You can add a boolean variable in the model class of the list you use to populate the recycler view, and than on its click you can change the boolean's value and call notifydatasetchange on the adapter, and in bind view you should keep an If else condition based on that boolean for the Bulb's image
ie. if true set one image if false set another
declare this :
int selectedPosition=-1;
inside onBindViewHolder:
public void onBindViewHolder(FiltersAdapter.ViewHolder holder, int position) {
if(selectedPosition==position)
holder.itemView.setImageResource(R.drawable.higlihgt_image);
else
holder.itemView.setImageResource(R.drawable.normal_image);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedPosition=position;
notifyDataSetChanged();
}
});
}
I am using nhaarman's ListviewAnimation library https://github.com/nhaarman/ListViewAnimations which works great.
But I am facing following issues:
The main problem I am facing is, I am not able to debug my code. I have directly copy/pasted the four required libraries into libs folder. Placing a debug point inside any of the listview methods like onItemLongClick() does not work.
The second problem is, drag-drop listView is not working in my code. Whenever I try to drag any list item, on dropping the list item, the item takes the same position from which it was dragged.
Here's the code I have used:
listview.enableDragAndDrop();
listview.setDraggableManager(new TouchViewDraggableManager(
R.id.list_row_draganddrop_textview));
listview.setOnItemMovedListener(this);
listview.setOnItemLongClickListener(this);
#Override
public void onItemMoved(final int originalPosition, final int newPosition) {
if (mToast != null) {
mToast.cancel();
}
mToast = Toast.makeText(getApplicationContext(), "Moved"
+ swingBottomInAnimationAdapter.getItem(newPosition)
+ newPosition, Toast.LENGTH_SHORT);
mToast.show();
}
#Override
public boolean onItemLongClick(final AdapterView<?> parent,
final View view, final int position, final long id) {
if (listview != null) {
listview.startDragging(position - listview.getHeaderViewsCount());
}
return true;
}
Whenever I try to drag any list item, on dropping the list item, the item takes the same position from which it was dragged.
Of course. Handling the change in position is your responsibility, and you should take care of it inside the onItemMoved callback:
#Override
public void onItemMoved(final int originalPosition, final int newPosition) {
if (mToast != null) {
mToast.cancel();
}
mToast = Toast.makeText(getApplicationContext(), "Moved"
+ swingBottomInAnimationAdapter.getItem(newPosition)
+ newPosition, Toast.LENGTH_SHORT);
mToast.show();
// Adapt the following to your implementation
if (originalPosition != newPosition) {
YourObject item = (YourObject) yourAdapter.getItem(originalPosition);
yourAdapter.moveItem(item, newPosition);
}
}
The method mentioned above would look something like:
public void moveItem(YourObject item, int newIndex) {
if (mEntries != null) {
mEntries.remove(item);
mEntries.add(newIndex, item);
notifyDataSetChanged();
}
}
If you go through the source code, you'll see that what you are dragging around is a Bitmap. The list item is sitting at its original position.
For others having the same problem - Niek Haarman has answered this question on GitHub here.
Don't see GitHub going down soon, but as it is good tone to paste the answer too, here it is:
#Override
public long getItemId(int position) {
return position;
}
#Override
public boolean hasStableIds() {
return true;
}
position is not a stable id here. You need a stable id for the item
which does not depend on the position.
use
import com.nhaarman.listviewanimations.ArrayAdapter;
instead of
import android.widget.ArrayAdapter;
that is the reason it doesn't calling onItemMoved
I have a custom adapter that renders two (2) checkboxes, a picture and the name of the client. All the information needed for the adapter is fetched from an ArratList that contains the Client class.
Every row needs to have both checkboxes checked (selected) for the client in order to process the purchase order, in case that a particular client has one checkbox checked-off and the other checkbox not, that raises a flag as MISMATCH. To make a valid order both checkboxes need to be checked-off.
We are implementing a button for verification, which will find any mismatch in the adapter and then hightlight the mismatches.
EDITION: After pressing the verificationBtn I am able to identify if any row has mismatch on checkboxes, for example, if checkbox1 was checked and checkbox2 not. that will mark the row as mismatch. I am using the position of my checkboxes based on clientList that is an arraylist of List clientList.
QUESTION: How can I get the position that the viewHolder has in order compare against the clientList position? Is there any way I can force the viewHolder to store the position and get it back and make the comparison with cli.getClient_number() ?
So far I have tested two different ways with no luck:
Method 1:
viewHolder.clientName.setBackgroundColor((Interger.parseInt(cli.getClient_number()) ) == position ? Color.GREEN : Color.TRANSPARENT);
Method 2
viewHolder.clientName.setBackgroundColor(Color.GREEN);
here the code that I am implementing.
// This goes in my main Client Activity
Button verificationBtn = (Button) findViewById(R.id.verificationBtn);
verificationBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
buffer.setLength(0);
mismatchTv.setText("");
for (Client cli : clientList) {
if (cli.isCheckboxOneSelected() != cli.isCheckboxTwoSelected()) {
//We had defined above the following buffer = new StringBuffer();
buffer.append((ah.parseInt(cli.getClient_number(), 0) - 1) + ", ");
cli.setMismatch(true);
//We are passing here the ID that correspond to the client mismatch
list_adapter.setBackgroundColor(Integer.parseInt(cli.getClient_number()) - 1);
setListAdapter(list_adapter);
Log.w("cli.getClient_number() ", String.valueOf(Integer.parseInt(cli.getClient_number()) - 1));
}
}
// We display any mismatch on a TextView on top of the screen
if (buffer.length() != 0) {
//This is a TextView on top of the screen
mismatchTv.setText("Error en Client(s) "
+ buffer.toString());
}
// This goes inside of the ClientArrayAdapter
public void setBackgroundColor(int position) {
Log.w("inside of setBackgroundColor method", "True");
switchIndex = 1;
positionFetched = position;
}
// This goes inside of the ClientArrayAdapter
// and inside the body of public View getView(int position, View convertView, ViewGroup parent) {
switch (switchIndex) {
case 1:
viewHolder.cbone
.setButtonDrawable(R.drawable.btn_checkbox_selector);
viewHolder.cbtwo
.setButtonDrawable(R.drawable.btn_checkbox_selector);
Log.w("switch 1 was called ", "True");
for (Client cli : clientList) {
if (cli.isCheckboxOneSelected() != cli.isCheckboxTwoSelected()) {
Client cli = getItem(positionFetched);
if (cli.isMismatch()) {
cli.setColor(Color.BLACK);
Log.e("if (cli.isMismatch()) ", "");
//HERE WE ARE TRYING TO HIGHLIGHT THE ROW WITH MISMATCH
//WHY THIS LINE DOES NOT WORK?
//THE ISSUE THAT I AM GETTING IS THAT I CANNOT CONTROL WHAT ROW TO AFFECT
//IN THE VIEW HOLDER
viewHolder.clientName.setBackgroundColor(Color.GREEN);
}
}
}
break;
default:
viewHolder.cbone.setButtonDrawable(R.drawable.disabled_cb);
viewHolder.cbtwo.setButtonDrawable(R.drawable.disabled_cb);
break;
}
// This goes inside of the ClientArrayAdapter
static class ViewHolder {
public TextView clientName;
public TextView clientNumber;
public ImageView imageView;
public CheckBox cbtwo;
public CheckBox cbone;
public int position;
}
After three days trying to figure out what's wrong with this code, I finally found the solution moving the Method #1 just at the very end of the getView method. :-)
I want to set the background color of clicked TextView included in LinearLayout. But I am unable to set the respective background. I faced not
clear previous clicked background . if I clicked all then set all background color.
Would you suggest me ,
how to set clickable TextView included in LinearLayout background.
Here is my sample code:
holder.txtName = (TextView) convertView.findViewById(R.id.row_cell_text_dummy_multilevel);
holder.l_select = (LinearLayout) convertView.findViewById(R.id.linear_select);
holder.txtName.setTag(position);
holder.txtName.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
select_pos=(Integer) holder.txtName.getTag();
if (position==select_pos) {
holder.l_select.setTextColor(Color.RED);
}else {
holder.l_select.setTextColor(Color.WHITE);
}
}
});
I managed to get this much done, though you will have to do some homework and find out how to reflect the changes yourself. At the moment, the change gets reflected only when the view is scrolled.
But i hope it helps you.
1.declare a static variable that sets the position clicked on
private static int selectedPostion;
2.set the selectedPosition's value to -1 in the constructor
3.in the getView method in the onclickListener do this:
int value = (Integer)((TextView)v).getTag();
Log.e("tag","(TextView)v).getTag() : " + value);
Log.e("tag", "position : " + position);
if(value == position) {
selectedPostion = position;
}else {
selectedPostion = -1;
}
4.Under the onClick code entirely before return view write this:
if(selectedPostion == position) {
view.setBackgroundColor(mContext.getResources().getColor(R.color.even_color));
// or holder.l_select.setTextColor(Color.RED);
}else {
view.setBackgroundColor(mContext.getResources().getColor(android.R.color.white));
// or holder.l_select.setTextColor(Color.WHITE);
}
Hope it helps!
I have created custom View called Color. I use object of Color to fill GridView (same issue is in ListView also).
My task is to let user choose one color and highlight it.
Previously I do something like that but I used only in building widgets and everything worked. This time I use my own.
This cose is for item clicking:
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int color = (int)id;
Log.d(TAG, "Selected color: " + id);
view.setSelected(true);
view.invalidate();
}
Color.onDraw:
#Override
public void onDraw(Canvas canvas) {
if (isSelected()) {
Log.d(TAG, "color draw selected");
} else {
Log.d(TAG, "not selected " + color);
}
}
Also I set setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); to this GridView (AbsListView.CHOICE_MODE_MULTIPLE don't help also)
In log I see:
Selected color: 8355711
not selected 16711680
not selected 16743680
not selected 8355711
I am sure, Color items is not recreating more than on time.
I tried change GridView to ListView, user default widget (overrided only onDraw()). Nothing helps. Maybe I forgot something?
In my opinion GridView somehow drop selected status.
If you need more info just tell.
Addition:
I checked with debugger. View with color 8355711 is same object in both functions.
I used setOnItemSelectedListener(this); to track item selection. But nothing happen in this listener.
The method isSelected() is comming from the GridView which is a child of View.
Basically when calling isSelected() you're saying: "is the gridview selected" which is not what you want.
What you want is: "is there any selected view in the grid view ?"
Which could be achieved using getSelectedView()
As the documentation says, you will get a reference to the selected view or null if none is selected.
Also make sur your GridView is properly initialized to handle item selection.
EDIT : Ok i understand that isSelected() is called from the Color view. My first guess is then useless.
But I think you should try to make your item selected using the setSelection() of the GridView object.
Add something like:
myGridView.setSelection(position);
I fix this issue my self by making my own select. Its workaround.
In Color class added:
private boolean selected = false;
public boolean isSelected2() {
return selected;
}
public void setSelected2(boolean selected) {
this.selected = selected;
}
#Override
public void onDraw(Canvas canvas) {
....
if (isSelected2()) {
//draw selected state
} else {
....
}
On ColorChooser grid:
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
...
int i = getChildCount();
while (--i >= 0)
((Color)getChildAt(i)).setSelected2(false);
((Color)view).setSelected2(true);
....
}
Reason why I not to override natice setSelected(boolean state) is some other code in grid every time make all items in deselected state. I don't know why, because in other places same more native code work very fine.