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.
Related
As a little eperiment, I'm trying to do the following.
I have an AXML describing a vertical linear layout which contains a listview (only filling 200dp of the vertical linear layout ). The AXML is inflated when the activity starts with SetContentView. Then the listview is correctly populated with values using its Adapter.
In the GetView method of the listview Adapter, I am trying to also dynamically create a button and add it to the linear layout, but for some reason the button is not added.
If I try to add the button in the constructor method of the Adapter instead, it is correctly added.
Can you tell me what could be possibly going wrong?
Let me add some code:
class TracksAdapter : BaseAdapter<string> {
Activity context;
List<Dictionary<string,string>> trackList;
// constructor
public TracksAdapter (Activity context, List<Dictionary<string,string>> trackList) {
this.context = context;
this.trackList = trackList;
// Just as a little test, if I create the button from here it will be correctly added to linear layout:
var ll = context.FindViewById<LinearLayout>(Resource.Id.linLayForResultsActivity);
Button b1 = new Button(context);
b1.Text = "Btn";
ll.AddView(b1);
}
public override View GetView(int position, View oldView, ViewGroup parent) {
// if I create the button from here it will not be added to the layout
var ll = context.FindViewById<LinearLayout>(Resource.Id.linLayForResultsActivity);
Button b1 = new Button(context);
b1.Text = "Btn";
ll.AddView(b1);
// this other code is working
View view = context.LayoutInflater.Inflate(Resource.Layout.ResultItem, null);
var artistLabel = view.FindViewById<TextView>(Resource.Id.resultArtistNameTextView);
artistLabel.Text = trackList[position]["trackArtistName"];
return view;
}
}
Update: adding some more context information because I know this can be a bit weird to understand without it:
In GetView, I don't need to return the new button I am trying to create there. GetView only need to return a listview view item, but, along its execution, GetView also has to create and add a button to the linear layout containing the listview.
The real code is much more complex than that. I have simplified it in the question. In the real code, the listview items are made of text and a button. The GetView also attaches event handlers to the buttons. Then what I need is, when a user clicks a button in any of the listview items, another button is added below the listview. So I need the code for adding another button to be in GetView, and the button needs to be added outside of the listview, ie. to the linear layout containing the listview.
Use the LayoutInflator to create a view based on your layout template, and then inject it into the view where you need it.
LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = vi.inflate(R.layout.your_layout, null);
// fill in any details dynamically here
TextView textView = (TextView) v.findViewById(R.id.a_text_view);
textView.setText("your text");
// insert into main view
ViewGroup insertPoint = (ViewGroup) findViewById(R.id.insert_point);
insertPoint.addView(v, 0, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
I looked in you code, you are returning view, while you add the button to ll, you should return ll
what you return in getView() is what you see in the list item layout, since you're adding the button to ll and returning view, the button won't appear.
you can add the button to view as you implementation
Also check this:
Try using boolean addViewInLayout (View child, int index, ViewGroup.LayoutParams params)
http://developer.android.com/reference/android/view/ViewGroup.html#addViewInLayout(android.view.View, int, android.view.ViewGroup.LayoutParams)
It's working... Without making any changes now it's working as it should... ! Ugh!
I really don't know what I was doing wrong here... probably it was because of some sort of caching of older version of the installed APK.. ? I know this sort of stuff can happen, and that's why I've always been uninstalling the app before deplyoing the new version to the device... but still...!
I am working on to update image of one button in a row inside custom listview. I have created a custom adapter class for the listview. On click of the button inside one row of listview I have open a custom dialog. Onclick of the OK button of dialog now I want t change the image of the button inside that listview.
Currently I have just made the static button inside the listview and passed the object of that button to the custom dialog method. I am using the simple listview not the fragments.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ItemInfoViewHolder viewHolder;
Log.d("Inside Get View", ""+position);
if (convertView == null) {
convertView = listInflater.inflate(R.layout.iteminfo_view_row, null);
viewHolder = new ItemInfoViewHolder();
viewHolder.itemSelection = (Button)convertView.findViewById(R.id.itemselectionTextview);
convertView.setTag(viewHolder);
}else{
viewHolder = (ItemInfoViewHolder)convertView.getTag();
}
try{
viewHolder.itemSelection.setId(itemsInfo.get(position).getId());
);
viewHolder.itemSelection.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("Item Id"+v.getId());
Toast.makeText(mContext, "Item Button Clicked", Toast.LENGTH_SHORT).show();
int itemId = v.getId();
SelectPopup selectPopup = new SelectPopup(mContext, R.style.myCoolDialog);
selectPopup.selectQuantity(itemsInfo,itemId,viewHolder.itemSelection);
}
});
}catch(Exception e){
e.printStackTrace();
}
return convertView;
}
Here viewHolder.itemSelection is the object of that button which I am passing to the custom dialog method. By this the image is update randomly on the listview on any row.
Please suggest me some better idea to do that.
Brief explanation:
An Adapter acts as a controller of your datamodel, in your case a List<itemsInfo>, and updates its assigned ListView accordingly inside the getView()-method.
Your goal is to change the visual state of the ListView whenever you do a certain action, a click. This is simply done by changing the datamodel behind the Adapter of your ListView whenever you perform your action and ask your ListView to redraw itself with help of the Adapter.
In code:
Add a field to your itemsInfo that will hold a certain state. This can be in any format or form but for now, let's use a boolean called isPressed.
In your getView(), your View will initialize itself depending on this pressed state.
viewHolder.itemSelection.whatevermethodyouwant(itemsInfo.get(position).isPressed)
When you want to change the state of your row, simply change the datamodel at the given position and update the ListView again.
viewHolder.itemSelection.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
itemsInfo.get(position).setPressed(whatever);
notifyDataSetChanged(); // This is a call for your Adapter and will refill the ListView
}
});
This is just pseudo code to explain the flow of events. Hope it will help you to improve your implementation.
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.
In a simple card game that i want to develop, I have three buttons: button1,button2 and button3. button1 creates two imageviews in a tablerow and displays the image. When button2 and/or button3 is clicked, it dynamically adds imageview on the tablerow through layout inflater. When game is over, I want user to click button1 and start things all over again. I am able to do that but the problem is, the imageviews that were previously displayed by clicking button2 and button3 also displays. I want them to be removed when button1 is clicked. How can I remove them on click of button1?
Please help me!
Just like you added views, you can remove them. Just call removeViewAt(int index) or removeView(View view) on the parent container to remove the view(s) you want.
Alternatively, if you foresee reusing them, you can just set their visibility to GONE. Then you could bring them back without the expense of inflating them again.
If you're letting the inflater automatically attach the inflated imageviews to the parent, then you'll have to keep track of the position of the added views. You can use getChildCount on the parent just before inflating to find the index of the next view that will be added.
you can use ViewGroup.removeView(View v);
something like this:
tblRow.removeView(button2);
here is how I add then remove a View 5 seconds later (in another context)
final LinearLayout linearLayout = context.getResources().getLayout(R.layout.activity_main)
LayoutInflater inflater = LayoutInflater.from(linearLayout.getContext());
final View details = inflater.inflate(R.layout.extra_details, linearLayout, false);
linearLayout.addView(details);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (linearLayout.findViewById(R.id.extra_details) != null){
linearLayout.removeView(details);
}
}
}, 5000);
the same use scenario is in the context of onClickListener.
Check more here https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/
//add view
LayoutInflater inflater = (LayoutInflater)this.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
final View buttons = inflater.inflate(R.layout.activity, null );
addContentView(buttons, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
//remove view
((ViewManager)buttons.getParent()).removeView(buttons);
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
}