like unlike button recyclerView image - android

I have an android app in which users can like and unlike an image.I'm using recyclerView.I Just disable the button(Like/Unlike) once user clicked. Problem, when I click on button like , the apps go to main activity and the button Like doesn't change to unlike What I have done :
1 ) layout that holds the each recycler view layout item
2 ) A view holder for creating each layout
3 ) A Model Class to holds the data
4 ) Recycler Adaptor which deals with the data for the Each Layout item
Hier ist my view holder
//Initializing Views
public ViewHolder(View itemView) {
super(itemView);
imageView = (NetworkImageView) itemView.findViewById(R.id.imageViewHero);
textViewName = (TextView) itemView.findViewById(R.id.textViewName);
//textViewPublisher = (TextView) itemView.findViewById(R.id.textViewPublisher);
likeImageView = (ImageView) itemView.findViewById(R.id.likeImageView);
likeImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int id = (int)likeImageView.getTag();
if( id == R.drawable.ic_like){
likeImageView.setTag(R.drawable.ic_liked);
likeImageView.setImageResource(R.drawable.ic_liked);
}else{
likeImageView.setTag(R.drawable.ic_like);
likeImageView.setImageResource(R.drawable.ic_like);
}
}
});

I answered this type of questions over and over. You didn't search enough and you didn't understand how ListView or RecycleView works. Changing current state of views ( such as changing text of TextView or changing resource of ImageView) is the wrong thing. You need data set (a list related to items in ListView) and you need to change corresponding data of the list and call notifyDataSetChanged() method of your adapter.
Don't forget. getView() method of your adapter is called every time any view of your list become on the screen and if you update only the view (instead of change data) your view will show the past value of item because your data didn't changed.
Look link below and search much more about how ListView and RecycleView works.
How ListView's recycling mechanism works

Related

Android, set visibility within list item layout

I am trying to display a delete button on every list item in my list view when the edit button is clicked. I am using setVisibility elsewhere in the app, so I tried to copy that code, but the issue in that the layout elements in the list items are not part of the layout xml file that the fragment implements, they are in a special one used by my CursorAdapter. I can find the desired hide-able elements using a layout inflator so I no longer get a nullPonterException, however the visibility does not change on button click like it should.
// Onclick method for Edit button
final Button buttonE = (Button) rootView.findViewById(R.id.editNotesButton);
buttonE.setTag(0);
//cannot use rootView as that points to fragment_main
final LayoutInflater factory = getLayoutInflater(savedInstanceState);
final View noteItemView = factory.inflate(R.layout.note_list_view_item, null);
final LinearLayout deleteButton = (LinearLayout) noteItemView.findViewById(R.id.delete_button_group);
final LinearLayout circleButton = (LinearLayout) noteItemView.findViewById(R.id.circle_button_group);
buttonE.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {
final int status =(Integer) v.getTag();
if(status == 1) {
buttonE.setText("Edit");
circleButton.setVisibility(View.VISIBLE);
deleteButton.setVisibility(View.GONE);
v.setTag(0); //pause
} else {
buttonE.setText("Done");
circleButton.setVisibility(View.GONE);
deleteButton.setVisibility(View.VISIBLE);
v.setTag(1); //pause
}
}
}
);
Firstly,I will figure out why your code doesn't work.You inflate noteItemView,but it doesn't bind to view in the screen,that is your 'noteitemview' won't show forever,so your delete button in that view will not visiable.
Then I will show my solution.
As you say,every list item has a delete button,what you should do is to control their visibility,so first make sure in your View binded to listview item has such a button as a childView of listview item view.In your getView of custom CursorAdapter,add logic to handle the delete button's visibility,for example,every list item data has a boolean variable named isDeleteButtonShow,then by control the variable's value to control the delete button's visibility,once visibility should change,update the data bind to listview and call adapter.notifyDataSetChanged.Hope that could help you.

Android multiple listviews with checkbox

I'm new to Android programing. I need to create a list of 1000 goods for users to click and check or the one they want to buy. I've created the array list and added it to my custom adapter and I have also added it to my list view. my problem is how to get the position for each item selected and I need clarification on the getView and the ViewHolder. I'm not working with toast
See the below tutorials,
http://sunil-android.blogspot.in/2013/04/android-listview-checkbox-example.html
http://developerandro.blogspot.in/2013/09/listview-with-checkbox-android-example.html
http://aboutyusata.blogspot.in/2013/11/how-to-make-listview-with-checkbox-in.html
Hope it helps.
You have to use ListView getCheckedItemPositions()
/**
* Returns the set of checked items in the list. The result is only valid if
* the choice mode has not been set to {#link #CHOICE_MODE_NONE}.
*
* #return A SparseBooleanArray which will return true for each call to
* get(int position) where position is a checked position in the
* list and false otherwise, or <code>null</code> if the choice
* mode is set to {#link #CHOICE_MODE_NONE}.
*/
public SparseBooleanArray getCheckedItemPositions() {
if (mChoiceMode != CHOICE_MODE_NONE) {
return mCheckStates;
}
return null;
}
getView() method is called when new list item that is adapted is being shown on your screen. That is why you need to take good care of the memory and setTag() for every item you inflate. Then when old item is viewed again you will not render it like a new one but get it by the tag you submitted for that item.
Example: If you have 1000 items only couple of those will be shown on the screen and your program will call getView() for those items that are visible plus for couple of items bellow those that are visible so you don't see the lag in inflation while scrolling.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if(view==null)
{
LayoutInflater inflater=getLayoutInflater();
view=inflater.inflate(R.layout.list, parent, false);
TextView textView=(TextView)view.findViewById(R.id.text_hint);
ImageView imageView=(ImageView)view.findViewById(R.id.img);
// here we will setTag() our view later
}
//... (here we will manage the views and set some click listeners)
Now, what is a viewHolder?
The ViewHolder basically is the private class inside your adapter that is used to keep you inflated layout elements together and to let you manipulate those view after you got the using findViewById(int resId).
Some code:
private class ViewHolder{
public ImageView imageView;
public TextView textView;
public ViewHolder(ImageView imageView,TextView textView) {
this.imageView = imageView;
this.textView = textView;
}
}
Now to setTag() as promised.
view.setTag(new Holder(imageView,textView));
Now with this in mind you can get your ViewHolder using the code above and views that you got in the first part of my code. (this is what we will write instead of 3 dots)
ViewHolder h = (Holder) view.getTag();
h.textView.setText(ar[position]);
int resID = getResources().getIdentifier(pic[position], "drawable", getPackageName());
h.imageView.setImageResource(resID);
// here I did set some source to my imageView that is in my layout, but
// you can do whatever you want with these views. And that is what I'm
// going to explain later in this text.
return view;
}
Okay, what next?
After getting the ViewHolder from tag you have your entire layout as a View that can get his OnClickListener easily. Or just a checkBox can get OnCheckedChangeListener.
Inside methods for this listeners you can send the data to you controller (in case you are using MVC model) or to your activity that hosts this View, where you can save the state of the checkbox and title of the item that has been clicked.
For example you can do something like this on your corresponding listener method:
(MainActivity)context.markAsChecked(String title);
But in this case you will also need to have the opposite method for unchecking
(MainActivity)context.markAsUnchecked(String title);
and you will have to handle this in your MainActivity properly by browsing through the array of data that has been selected.
The second solution is to have :
(MainActivity)context.toggleState(String title);
And to handle both events checked and unchecked.
Your method in your Activity would need to do something similar to this:
public void toggleState(String title){
if (data.contains(title))
data.remove(title);
else data.add(title);
}
Then after your user checks what he wants you will have all the checked elements in your data array that in this case is ArrayList. You can also you HashMap for this if you like or something else too.
Hope this helps.
I will be more than happy to answer all of your questions if have some more.
Maybe controller implementation is something that you would like to consider in this case. That would mean that you would be using MVC model for better control of your app and data, and to delegate the tasks to responsible classes and methods. Not to put everything in one Activity :)
Bye

Accessing a UI component (Button) inside several other UI components (ExpandableListView - GridView) in Android

In a xml, I am having LinearLayout.
Inside that I am using an ExpandableListView.
Every expand item contain just one view which is a GridView.
A GridView cell compose with three UI components which are ImageView, TextView and a Button.
How I have got control about those three UI components is as follow,
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = (LayoutInflater) imageAdapterContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.single_grid_item, null);
viewHolder = new ViewHolder();
viewHolder.singleImageView = (ImageView) convertView.findViewById(R.id.singleGridItem_imageView);
viewHolder.singleTextView = (TextView) convertView.findViewById(R.id.singleGridItem_textView);
viewHolder.singleDownloadButton = (Button) convertView.findViewById(R.id.singleGridItem_download_button);
}
}
// ViewHolder is a static nested inner class
Things are working prety fine. That means each cell identify as different cells.
They have different images, and appropriate TextView labels and also Button click event also working fine.
For the button click I have used a downloading with a ProgressDialog. That also working fine.
What I want is disable the Button when the downloading in progress.
Downloading happening in a seperate AsyncTask class.
Please tell me how can I disable the button which user has clicked for downloading.
set the click able property of the button to false in the on click method and enable it on post execute -- (view v)
then set the property of v
Most of the time I have to wrte the answer for my own question.
This one also the same.
I have figure out the way.
I have override the button click event in the getView() method as follow.
viewHolder.singleDownloadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Some code goes here...
new DownloadZipAsyncTask(imageAdapterContext, view).execute(zipFileUrl);
}
});
By the time I click the Download button, I am passing the button view to the DownloadZipAsyncTask class.
In that class, I am again creating Button instance and set the view invisible as follow in onProgressUpdate()
Button mybutton = (Button) view.findViewById(R.id.singleGridItem_download_button);
mybutton.setVisibility(View.INVISIBLE);
For button, it is working. But I can't change the ImageView or the TextView like that.
Because in the click event, we only pass the Button view only.
Therefore I am again in a problem with how to update a progress bar like that.
Again, ProgressDialog is not a problem, only the ProgressBar UI component give the problem.

Scrolling a Gallery enables pressed state and removes click listener from subitems

I have a gallery of fairly complicated items. Each item is composed of an image and 2 buttons. When the gallery loads everything works, the buttons do what they are supposed to, and the pressed state for the buttons happens only on actual press of the buttons.
However as soon as I scroll the gallery, the buttons stop working and clicking anywhere enables the pressed state for the buttons.
I have tried embedding everything in a LinearLayout that doesn't pass on OnDown events as per this answer however, this just blocks click events.
I am aware that Gallery is not the ideal widget for complicated layouts like this, but I am wondering if there is a better workaround for this issue.
UPDATE:
I will try to explain the architecture a bit. I have a FragmentActivity which contains a ListFragment, which is made up of just a ListView.
The ListView is made up of groups of smaller elements(Bettable) along with some meta information. These groups are implemented as Gallerys. Specifically
I have extended Gallery (called OneGallery), that does several things, it makes sure that only one item is scrolled at a time, and also
transforms the gallery items as the scrolling is happening. Here is the code for that
Here is the adapter for the Gallery
And here is the code for the Bettable layout
Try to add a new wrapper layout around the child view and override the setPressed. The gallery will stop passing its state on the children and the mentioned undesired behavior that you describe will be fixed.
This is views recycling. Try to use ViewHolder pattern and set up item state for every getView call. If you want to do that you must hold view state in your complex object. For example your complex object contains TextView, ImageView and CheckBox
public View getView(int position, View convertView, ViewGroup parent) {
ComplexObject co = objects.get(position);
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
ViewHolder holder;
// When convertView is not null, we can reuse it directly, there is no need
// to reinflate it. We only inflate a new View when the convertView supplied
// by ListView is null.
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
// Creates a ViewHolder and store references to the two children views
// we want to bind data to.
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
holder.checkbox = (CheckBox)convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
holder = (ViewHolder) convertView.getTag();
}
// Bind the data efficiently with the holder.
holder.text.setText(co.getText());
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
holder.checkbox.setChecked(co.isChecked());
holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
co.setChecked(isChecked);
}
});
return convertView;
}
protected class ViewHolder{
TextView text;
ImageView icon;
CheckBox checkbox;
}
Hope it will be helpful

Help regarding onClick() event on an item of ListView custom row layout

I have a ListView whose rows are formatted by me. Each row has a mix of ImageView and TextView.
I have also implemented my own adapter and am able to draw each row through it.
Now, I would want something like this-
User clicks on an ImageView (not anywhere else on the row, but only this ImageView should respond to clicks)
I get to know the position of the row whose ImageView was clicked.
I have tried many things for this and have wanted my code to be as efficient as possible (in terms of overkill).
Currently i can capture the click event on that particular ImageView only, but I can't know which row was clicked.
I have provided an attribute in the Row XML like this-
<ImageView android:id="#+id/user_image"
android:padding="5dip"
android:layout_height="60dip"
android:layout_width="60dip"
android:clickable="true"
android:onClick="uImgClickHandler"/>
And in my code, I have a method like this:
public void uImgClickHandler(View v){
Log.d("IMG CLICKED", ""+v.getId());
LinearLayout parentRow = (LinearLayout)v.getParent();
}
I can get the parent row (perhaps) but am not sure how to go further from here.
Can someone please help?
Please refer this,
Me just writing the code to give you idea, Not in correct format
class youaddaper extends BaseAdapter{
public View getView(int position, View convertView, ViewGroup parent){
LayoutInflater inflate = LayoutInflater.from(context);
View v = inflate.inflate(id, parent, false);
ImageView imageview = (ImageView) v.findViewById(R.id.imageView);
imageview.setOnClickListener(new imageViewClickListener(position));
//you can pass what ever to this class you want,
//i mean, you can use array(postion) as per the logic you need to implement
}
class imageViewClickListener implements OnClickListener {
int position;
public imageViewClickListener( int pos)
{
this.position = pos;
}
public void onClick(View v) {
{// you can write the code what happens for the that click and
// you will get the selected row index in position
}
}
}
Hope it helped you
Another option is to use the methods setTag() and getTag() of the view. You set it in your getView like this:
imageView.setTag(new Integer(position));
Then in the onClick() you can find the tag by:
Integer tag = v.getTag();
This will then be used to correlate the image view to the position of the listview item.
Note that this approach will give problems if the listview can lose items from the middle, so that the item positions change during the lifetime of the listview.
you can simply do like this:
in the getview method of our adapter
Button btn1 = (Button) convertView.findViewById(R.id.btn1);
btn1.setOnClickListener(mActivity);
further you can handle the onclick event in your activity,,
for the context of the activity here mActivity just pass the this in the constructer of the adapter and cast it here into the activity like
MyActivity mActivity=(MyActivity)context;
in the adapter.
thanx
This appears to work in a ListActivity whose item layout contains an ImageView with android:onClick="editImage":
public void editImage(View v) {
int[] loc = new int[2];
v.getLocationInWindow(loc);
int pos = getListView().pointToPosition(loc[0], loc[1]);
Cursor c = (Cursor) adapter.getItem(pos);
// c now points at the data row corresponding to the clicked row
}

Categories

Resources