I am designing a chess Board application and I am using a gridview for storing 64 buttons and assigning id to them starting from 0 to 63. But the ids are starting from 2 instead of 0, I can't understand why that is happening.
I am using ButtonAdapter class I made and the following is its getView() method and I set text of each button same as its id to make sure they are getting correct ids.
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
Button button;
if(view == null){
button = new Button(mContext);
}else{
button = (Button)view;
}
button.setId(mIndex);
button.setText(button.getId()+"");
button.setTextSize(5);
button.setPadding(0,0,0,0);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(mContext, view.getId()+"", Toast.LENGTH_SHORT).show();
}
});
mIndex++;
return button;
}
mIndex is initialized to 0 in my constructor like following
private Context mContext;
private int mIndex;
public ButtonAdapter(Context context){
mContext = context;
mIndex = 0;
}
and the screenshot of result I am getting is below
Please help, I am a beginner. Sorry for any mistakes, thanks in advance.
Don't use mIndexvariable and increment because it will create issue when you will scroll.
You can use adapter position instead of mIndex.
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
Button button;
if(view == null){
button = new Button(mContext);
}else{
button = (Button)view;
}
button.setId(i);
button.setText(String.valueOf(i));
button.setTextSize(5);
button.setPadding(0,0,0,0);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(mContext, view.getId()+"", Toast.LENGTH_SHORT).show();
}
});
return button;
}
you can set the tag like this
button.setTag(Integer.valueOf(position));
and get that id by
Integer position = (Integer)view.getTag();
Related
I have a ListView which implements a custom adapter that contains a few TextViews and two Buttons.
Now when i try to add an item to that ListView, if it is already in the list i want to change the text of its row's TextView (Quantity) and make it + 1. But i can't quite figure out how to interact with that particular TextView.
Adapter code:
public class ItemAdapter extends ArrayAdapter<Item> {
public ItemAdapter(#NonNull Context context) {
super(context, R.layout.lay_list_items);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater li = LayoutInflater.from(getContext());
View v = li.inflate(R.layout.lay_list_items, null);
final Item item = getItem(position);
TextView nom = (TextView)v.findViewById(R.id.txtNom);
TextView description = (TextView)v.findViewById(R.id.txtDescription);
final TextView qty = (TextView)v.findViewById(R.id.txtQty);
Button btnAjouter = (Button)v.findViewById(R.id.btnAjouter);
Button btnRetirer = (Button)v.findViewById(R.id.btnRetirer);
nom.setText(item.nom);
description.setText(item.description);
qty.setText("1");
btnAjouter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int qtyCourante = Integer.parseInt(qty.getText().toString());
int newQty = qtyCourante + 1;
qty.setText(Integer.toString(newQty));
}
});
btnRetirer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int qtyCourante = Integer.parseInt(qty.getText().toString());
int newQty = qtyCourante - 1;
if (newQty > 0)
qty.setText(Integer.toString(newQty));
else
ItemAdapter.super.remove(item);
}
});
return v;
}
You need to save the count, and then use it.
Use ArrayList<Integer> or add one more field int count in your Model Class Item. It is better to add one more field in Item class.
Initialize it as 1 for all items.
And use the code,
qty.setText(String.valueOf(item.getCount()));//declare a method to get count field value, here getCount()
In your button click,
btnAjouter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
item.setCount( item.getCount() + 1 ); //declare a method to set value
notifyDataSetChanged();
}
});
And also
btnRetirer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if ( item.getCount() > 0)
item.setCount( item.getCount() - 1 );
else
ItemAdapter.super.remove(item);
notifyDataSetChanged();
}
});
notifyDataSetChanged(); should be invoked to update your changes.
Since you are using an ArrayAdapter as your base Class, if you want to add a new item, you can just call:
adapter.add(newItem);
adapter.notifyDataSetChanged();
and the adapter will help you handle the new item.
I need to update progress bar after i press the button inside my custom adapter.
Only when i declared view value as final i can do that. But it doesn't suit me.
What are the right solutions to do this ?
My custom adapter source:
public class DownloadListAdapter extends BaseAdapter implements DownloadManagerListener{
Context ctx;
LayoutInflater lInflater;
ArrayList<Product> objects;
View view;
DownloadListAdapter(Context context, ArrayList<Product> products) {
ctx = context;
objects = products;
lInflater = (LayoutInflater) ctx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.item, parent, false);
}
Product p = getProduct(position);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
progressBar.setProgress(p.size);
Button btSet = (Button) view.findViewById(R.id.btSet);
btSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//this does not work
progressBar.setProgress(100);
//this doesn't work too, it will work only when view will declared as final
ProgressBar pb = (ProgressBar) view.findViewById(R.id.progressBar);
pb.setProgress(100);
}
});
return view;
}
#Override
public void OnDownloadStarted(long taskId) {
//This method should also have access to view
}
#Override
public int getCount() {
return objects.size();
}
#Override
public Object getItem(int position) {
return objects.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
Product getProduct(int position) {
return ((Product) getItem(position));
}
}
As I understood when I read your code, you want to start download indicator (in this case, indicator is your progress bar). So you can try this way:
1. I assume that this is your DownloadManagerListener or you can change yours to this:
public interface DownloadManagerListener {
void OnDownloadStarted(long taskId, View view);
}
2. Change your button listener like this:
btSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ProgressBar progress = ((LinearLayout) v.getParent())
.findViewById(R.id.progressBar);
OnDownloadStarted(0, progress);
}
});
In this I assumed that your layout (R.layout.item) like that:
<LinelearLayout>
...
<ProgressBar android:id="#+id/progressBar"/>
...
<Button android:id="#+id/btSet"/>
</LinearLayout>
3. Finally your method OnDownloadStarted like this:
public void OnDownloadStarted(long taskId, View view) {
ProgressBar progressBar = (ProgressBar) view;
progressBar.setProgress(0);
}
UPDATE 1:
Base on author comment. I suggest following point:
1. Remove View view; from member off class and in getview method. Because when list view is populated, view reference to last item that has been call getView. So view member of adapter class is meaningless.
2. Change class which like this:
public class DownloadListAdapter extends BaseAdapter implements DownloadManagerListener{
Context ctx;
LayoutInflater lInflater;
ArrayList<Product> objects;
HashMap<Integer, ProgressBar> mProductDownloaderMap = new HashMap<Integer, ProgressBar>();
3. Chang getView() method like this:
if (convertView == null) {
convertView = lInflater.inflate(R.layout.item, parent, false);
}
Product p = getProduct(position);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
Button btSet = (Button) view.findViewById(R.id.btSet);
mProductDownloaderMap.put(position, progressBar);
btSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
OnDownloadStarted(position);// position is indicated taskID
}
});
4. On your dowload method:
public void OnDownloadStarted(long taskId) {
ProgressBar progressBar = mProductDownloaderMap.get(taskId);
progressBar.setProgress(0);
//Your download code here
}
Please let me know if I missunderstand your code/your purpose!
Also dont forget to mark this is anwsers if my answers is right for your question
Hope that help!
The view variable is global in the class so no need to make it final.
You should make the progressBar as final and change its progress inside button onClick method
This is in the inside of a BaseAdapter that gets called in a Fragment. The OnClickListener should remove the hole adapteritem but for some reason it only removes the content but it won't remove the frame. It allways keeps the size of the adapter just the content disapears, the underlining stays too.
public View getView(final int position, View convertView, ViewGroup parent) {
boolean memCache = true;
boolean fileCache = true;
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater)
activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.favorite_list_item, null);
}
TextView txtTitle = (TextView) convertView.findViewById(R.id.title);
txtTitle.setText(allFavorite.get(position).getTitle());
Button deleteButton = (Button) convertView.findViewById(R.id.delete_button);
deleteButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
((View) view.getParent()).setVisibility(View.GONE);
}
});
return convertView;
}
}
You should remove the data bind to your view from your data set and call a notifyDataSetChanged() afterward rather than hide the view itself.
Button deleteButton = (Button) convertView.findViewById(R.id.delete_button);
deleteButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
allFavorite.remove(position);
notifyDataSetChanged();
}
});
try like this,
deleteButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
adapter.remove(adapter.getItem(position));
}
});
hope it will help you
Your code just make view invisible, not delete them. You have to delete from adapter like this :
listItem.remove(position);
adapter.notifyDataSetChanged();
I have A listview, and in list view I have A textview. So this text view is visible in every item of listview. So when I click on any Textview then it's visibility mus be gone. But when I'll click on another textview then current must gone and previous must be visible.
In adapter class I tried a lot of things but I did't find the correct way. So how can I get this thing in getView().
holder.floorNo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (holder.floorNo.getId() == v.getId()) {
final int position1 = listView
.getPositionForView((LinearLayout) v
.getParent());
} else {
}
}
});
Here position1 is the current position of click. Pleas help me.
You can set tag of textview as holder.settag(holder.floorNo). on click lister of floorNo get this tag by Textview floorno = (Textview) v.gettag();
Here you will get the clicked textview and add code for visible / invisible .
I don't know Which adapter you are using .If you are using CursorAdapter then in CursorAdapter by overridien method newView() it is possible
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
((TextView) (convertView
.findViewById(R.id.main_body_item_title_second_pics)))
.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
// do your stub here
}
});
}
You can use a textview class member as a "reminder" to know which textview is hidden, something like this :
private View mHiddenView = null
private int mFloorNoId = 0
....
....
holder.floorNo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(mHiddenView !=null&&mFloorNoId!=0){
// Show textview that was hidden
mHiddenView.findViewById(mFloorNoId).setVisibility(VISIBLE);
}
// Assign clicked view to hidden one and FloorNo id
mHiddenView = v;
mFloorNoId = holder.floorNo.getId();
// And hide it
mHiddenView.findViewById(mFloorNoId).setVisibility(GONE);
}
});
maintain a list of boolean in your adapter indicating visibility of TextView holder.floorNo.
boolean[] visibilityArray;
in constructor
visibilityArray; = new boolean[ no. Of Elements in your adapter ];
in getView() method
holder.floorNo.setVisibility(visibilityArray[position]);
holder.floorNo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
notifyStateChange(position);
}
});
notifyStateChange(position) method defined as follows
private void notifyStateChange(int position) {
for(int i = 0; i<visibilityArray.length; i++){
visibilityArray[i] = true;
}
visibilityArray[position] = false;
this.notifyDataSetChanged();
}
I am making a list view that contains (amongst a few other things) 2 ImageViews and a TextView. The two ImageViews are plus and minus icons, when they are pressed, they need to update the number inside the TextView. They also need to trigger code that will update the sum of the TextViews, below the ListView.
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.basket_item, null);
holder.plus = (ImageView) convertView.findViewById(R.id.count_add);
holder.minus = (ImageView) convertView.findViewById(R.id.count_minus);
holder.counter = (TextView) convertView.findViewById(R.id.text_counter);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.id = position;
holder.counter.setId(position);
holder.counter.setText(count[position]);
holder.plus.setId(position);
holder.plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int id = v.getId();
if (count[id] < 999) {
count[id]++;
totalcount++;
}
}
});
holder.minus.setId(position);
holder.minus.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int id = v.getId();
if (count[id] > 1) {
count[id]--;
totalCount--;
}
}
});
return convertView;
}
}
class ViewHolder {
ImageView plus;
ImageView minus;
TextView counter;
int id;
}
I believe, to update the counter in the TextView, I need to somehow get my 'holder' inside the OnClickListner, however, as it is not declared as final, I can't.
Is there an easier way to do this, or am I missing a trick here?
Try implement the notifyDataSetChanged() that calls the getView once again. And after that invalidate the textView. But I am not fully sure about the need to call invalidate() here.
public void onClick(View v) {
int id = v.getId();
if (count[id] > 1) {
count[id]--;
totalCount--;
notifyDataSetChanged();
holder.counter.invalidate();
}
}
});
I am not sure about it.I hope it do. Try to paste this line under the Onclick method itself.
"holder.counter.setText('YOUR TEXT totalcount');"