我正在使用带ViewHolder模式的自定义列表适配器将视图扩展到我的列表中,该列表显示图像(width = match_parent
),左侧(图像下方)的一些文本和右侧的按钮(也在下方)图像)。
以下是适配器类的代码 -
public class DishItemListAdapter extends ArrayAdapter<DishItem> {
//declare fonts - BOLD and LIGHT
final Typeface tf_light = Typeface.createFromAsset(getContext().getAssets(),
"fonts/Roboto-Thin.ttf");
final Typeface tf_bold = Typeface.createFromAsset(getContext().getAssets(),
"fonts/Roboto-Regular.ttf");
//get item count
CartItemCount cartItemCount;
//count for dish at particular position
ArrayList<Integer> dishCountList = new ArrayList<>();
//for matching key string in SharedPrefs
String existingKeyString;
Typeface font_light, font_bold;
/* List of DishItem Objects shown on the Dashboard */
private List<DishItem> DishItemList = new ArrayList<DishItem>();
public DishItemListAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
this.font_bold = tf_bold;
this.font_light = tf_light;
}
/* Add a New DishItem Item (object) to the list of DishItems on the Dashboard i.e. DishItemList */
@Override
public void add(DishItem object) {
DishItemList.add(object);
super.add(object);
}
@Override
public int getCount() {
return this.DishItemList.size();
}
@Override
public DishItem getItem(int index) {
return this.DishItemList.get(index);
}
@Override
public View getView(final int position, final View convertView, ViewGroup parent) {
Log.e("getView() at " + position, "");
View row = convertView;
final DishItemViewHolder viewHolder;
// A ViewHolder keeps references to children views to
// avoid unnecessary (and expensive) calls to findViewById() on each row.
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.list_item_dish, parent, false);
//instantiate DishItem View Holder
viewHolder = new DishItemViewHolder();
//get BUTTON for Adding Dish to Cart
viewHolder.addToCart = (Button) row.findViewById(R.id.add_to_cart_button);
//BUTTONS for + and - (adding and removing items from cart)
viewHolder.addItemButton = (Button) row.findViewById(R.id.increase_item_count);
viewHolder.removeItemButton = (Button) row.findViewById(R.id.decrease_item_count);
//DISH NAME, CHEF NAME, DISH PRICE and DISH IMAGE
viewHolder.dishName = (TextView) row.findViewById(R.id.dish_name_textview);
viewHolder.chefName = (TextView) row.findViewById(R.id.chef_name_textview);
viewHolder.dishPrice = (TextView) row.findViewById(R.id.dish_price_textview);
viewHolder.dishImage = (ImageView) row.findViewById(R.id.dish_imageview);
//image absolute path
viewHolder.imageStorePath = new String();
//image for depicting whether image is VEG or NON VEG
viewHolder.veg_nonveg_indicator = (ImageView) row.findViewById(R.id.veg_nonveg_indicator);
//viewSwitcher for switching between BUTTON and - + button
viewHolder.viewSwitcher = (ViewSwitcher) row.findViewById(R.id.viewswitcher);
//indicator for item added to Cart
viewHolder.addedToCartIndicator = (TextView) row.findViewById(R.id.added_to_cart_text_indicator);
viewHolder.addedToCartIndicator.setVisibility(View.INVISIBLE);
//counter for number of items selected for a particular dish
viewHolder.dishQuantity = (TextView) row.findViewById(R.id.dish_quantity);
//set tag for the ViewHolder
row.setTag(viewHolder);
} else {
/* Get the ViewHolder back to get fast access to the DishItem UI widgets (views) */
viewHolder = (DishItemViewHolder) row.getTag();
}
//create object of Item Count Class
cartItemCount = new CartItemCount();
/* fetch DishItem View at current position (="position") */
final DishItem dishItem = getItem(position);
row.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("clicked"+position,"");
viewHolder.dishName.setText("CLICKED");
}
});
return row;
}
static class DishItemViewHolder {
TextView dishName;
TextView chefName;
TextView dishPrice;
TextView dishQuantity;
String imageStorePath;
boolean isDishItemSelected;
Button addToCart, addItemButton, removeItemButton;
ImageView veg_nonveg_indicator;
ImageView dishImage;
ViewSwitcher viewSwitcher;
TextView addedToCartIndicator;
}
}
问题
假设我在列表中添加了6个DishItem
bean(模型)。然后,当我对列表中的第一个项目执行onClick时,第一个项目的文本将更改为应该按下单击。此外,在日志中,在clicked:0
中说(因为第一个列表项的索引是0)。
但是第4个列表项的文本也更改为CLICKED,它不应该。
现在我读了this帖子,解释了ListView的回收机制。
但是,我不希望它以这种方式工作,因为我只想更新我点击的那些项目。 我在这做错了什么? 这种回收机制是否有任何解决方法只更新我点击的特定项目?
更新
问题解决了。我遵循了BlackBelt的方法,因此接受了他的回答,但我要感谢你们所有人的投入! :)
这是更新的getView()方法。
/**
*
* @param position The position of the item within the adapter's data set of the item whose view we want.
* @param convertView The old view to reuse, if possible.
* Note: You should check that this view is non-null and of an appropriate type before using.
* If it is not possible to convert this view to display the correct data, this method
* can create a new view. Heterogeneous lists can specify their number of view types,
* so that this View is always of the right type (see getViewTypeCount() and getItemViewType(int)).
* @param parent The parent that this view will eventually be attached to
* @return A View corresponding to the data at the specified position.
*/
@Override
public View getView(final int position, final View convertView, ViewGroup parent) {
View row = convertView;
final DishItemViewHolder viewHolder;
// A ViewHolder keeps references to children views to
// avoid unnecessary (and expensive) calls to findViewById() on each row.
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.list_item_dish, parent, false);
//instantiate DishItem View Holder
viewHolder = new DishItemViewHolder();
//get BUTTON for Adding Dish to Cart
//viewHolder.addToCart = (Button) row.findViewById(R.id.add_to_cart_button);
viewHolder.addItemButton = (Button) row.findViewById(R.id.add_to_cart_secondary_button);
viewHolder.removeItemButton = (Button) row.findViewById(R.id.remove_from_cart_button);
//DISH NAME, CHEF NAME, DISH PRICE and DISH IMAGE
viewHolder.dishName = (TextView) row.findViewById(R.id.dish_name_textview);
viewHolder.chefName = (TextView) row.findViewById(R.id.chef_name_textview);
viewHolder.dishPrice = (TextView) row.findViewById(R.id.dish_price_textview);
viewHolder.dishImage = (ImageView) row.findViewById(R.id.dish_imageview);
//image absolute path
viewHolder.imageStorePath = new String();
//image for depicting whether image is VEG or NON VEG
viewHolder.veg_nonveg_indicator = (ImageView) row.findViewById(R.id.veg_nonveg_indicator);
//indicator for item added to Cart
viewHolder.addedToCartIndicator = (TextView) row.findViewById(R.id.added_to_cart_text_indicator);
viewHolder.addedToCartIndicator.setVisibility(View.INVISIBLE);
//set tag for the ViewHolder
row.setTag(viewHolder);
} else {
/* Get the ViewHolder back to get fast access to the DishItem UI widgets (views) */
viewHolder = (DishItemViewHolder) row.getTag();
}
//get object for CART ITEM COUNT class
final CartItemCount cartItemCount = new CartItemCount();
//get current dish item (MODEL from Bean class)
final DishItem dishItem = getItem(position);
//disable any highlighting unless dish is selected (verified from SharedPreferences)
viewHolder.dishImage.setColorFilter(null);
//hide ITEM COUNT indicator over the image unless dish is selected (again, verified from SharedPreferences)
viewHolder.addedToCartIndicator.setVisibility(View.INVISIBLE);
//show the + and - buttons on the right and left (respectively) side on the Dish ImageView
viewHolder.addItemButton.setVisibility(View.VISIBLE);
viewHolder.removeItemButton.setVisibility(View.VISIBLE);
//get data from Preferences (to see which dish is selected)
SharedPreferences pref = getContext().getSharedPreferences("DishDetails", Context.MODE_PRIVATE);
Map<String, ?> allEntries = pref.getAll();
for (Map.Entry<String, ?> entry : allEntries.entrySet()) {
Log.d("KEY = " + entry.getKey(), " VALUE = " + entry.getValue().toString());
}
//get Count for each dish in the list and set Quantity in the Model (DishItem.java)
if (pref != null) {
int currentDishCount = pref.getInt("dishCount" + position, 0);
Log.e("Current DishCount", String.valueOf(currentDishCount));
if (currentDishCount > 0) {
getItem(position).setisDishItemSelected(true);
dishItem.setDishQuantity(currentDishCount);
Log.d("dish item" + position," selected");
}
}
//update Views for selected DishItems
if (dishItem.isDishItemSelected()) {
viewHolder.dishImage.setColorFilter(Color.parseColor("#80E0E0E0"));
viewHolder.addedToCartIndicator.setVisibility(View.VISIBLE);
viewHolder.addedToCartIndicator.setText(dishItem.getDishQuantity() + " items in cart");
}
viewHolder.addItemButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dishItem.setisDishItemSelected(true);
dishItem.setDishQuantity(dishItem.getDishQuantity() + 1);
//save data to preferences
SharedPreferences pref = getContext().getSharedPreferences("DishDetails", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putInt("dishCount" + position, dishItem.getDishQuantity());
editor.commit();
//increment Total Number of Items in Cart
int itemCount = cartItemCount.getitemCount();
cartItemCount.setitemCount(itemCount + 1);
Log.d("itemCount =", String.valueOf(itemCount));
//broadcast the value of itemCount to MainMenuActivity
Intent intent = new Intent("NEW_CART_ITEM");
intent.putExtra("value", cartItemCount.getitemCount());
getContext().sendBroadcast(intent);
Log.d("broadcast", "sent");
//notify adapter of change in underlying data (i.e. update View to show Changes in Model)
notifyDataSetChanged();
}
});
viewHolder.removeItemButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Old Dish Qty. ", String.valueOf(dishItem.getDishQuantity()));
//if dishCount has reached ZERO, set Dish as NOT SELECTED for buying
if (dishItem.getDishQuantity() == 0) {
dishItem.setisDishItemSelected(false);
} else {
dishItem.setisDishItemSelected(true);
dishItem.setDishQuantity(dishItem.getDishQuantity() - 1);
Log.d("New Dish Qty.", String.valueOf(dishItem.getDishQuantity()));
//decrement TOTAL number of items in Cart
int itemCount = cartItemCount.getitemCount();
cartItemCount.setitemCount(itemCount - 1);
Log.d("itemCount =", String.valueOf(itemCount));
//broadcast the value of itemCount to MainMenuActivity
Intent intent = new Intent("NEW_CART_ITEM");
intent.putExtra("value", cartItemCount.getitemCount());
getContext().sendBroadcast(intent);
Log.d("broadcast", "sent");
//recheck -> if dish Count has reached ZERO, set Dish as NOT SELECTED for buying
if (dishItem.getDishQuantity() == 0) {
dishItem.setisDishItemSelected(false);
}
}
//save Current Quantity of Dish Selected to SharedPreferences
SharedPreferences pref = getContext().getSharedPreferences("DishDetails", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putInt("dishCount" + position, dishItem.getDishQuantity());
editor.commit();
//notify adapter of change in underlying data (i.e. update View to show Changes in Model)
notifyDataSetChanged();
}
});
return row;
}
这个想法很简单(之前我不知道) -
致电
notifyDataSetChanged()
告诉适配器数据的变化,以便相应地调整视图。
答案 0 :(得分:2)
这种回收机制是否有任何解决方法只能更新 我点击的特定项目?
这里没有解决方法。您必须更改数据集(位置 - 您单击的项目),并要求Adapter
重绘ListView
个孩子。我强烈建议你也使用OnItemClickListener
。
答案 1 :(得分:0)
您应该将视图的状态重置为getView
中的默认状态,并在此之后应用项目的数据。它的工作原理如下:
TextView
的文本 - 不要认为它已包含正确的文本)您需要将项目的状态存储在某处 - 目前您使用TextView的文本执行此操作,并且由于回收行为而中断。正确的方法是向DishItem
添加一个字段,或者只创建一个新类来包含每个项目的状态(选中,重点等等 - 您要支持的所有状态)。在onClickListener
中更改状态的值,然后更改视图的内容,或者只需在适配器上调用notifyDataSetChanged
。