Android OnClickListener 不适用于自定义适配器

Android OnClickListener not working with custom adapter

我为 ListView 制作了一个自定义适配器,以便在同一行中显示一个 String 和一个 ImageButton。每次单击 add button 时都会生成一行。该字符串取自 EditText 字段,而 ImageButton bin_button 是动态分配的。一切正常,除了我无法让 bin_button 触发 OnClick 事件。

我已经尝试了几种解决方案。这里bin_button_listener是在add_button的OnClickListener外面生成然后设置的。我还尝试在每次创建新的 bin_button 时使用新的 OnClickListener 设置监听器。

这里是一些代码:

行布局list_string_button_layout.xml

<TextView
        android:id="@+id/list_item_string"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="8dp"
        android:paddingEnd="0dp"
        android:paddingTop="8dp"
        android:textSize="18sp"
        android:textStyle="bold"/>

<ImageButton
        android:id="@+id/delete_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="10dp"
        android:paddingEnd="5dp"
        android:background="#00ffffff"
        android:src="@drawable/ic_delete_black_18dp"
        android:layout_alignBottom="@+id/list_item_string"
        android:layout_alignParentEnd="true"
        android:focusableInTouchMode="true"
    /> 
</RelativeLayout>

Activity布局activity_search.xml

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/ingredient_text_input"
    android:hint="@string/start_typing_ingredient"
    android:layout_marginTop="52dp"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    />

<Button
    style="@style/Button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/add_button"
    android:backgroundTint="@color/colorPrimaryLight"
    android:id="@+id/add_button"
    android:layout_alignTop="@+id/ingredient_text_input"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"/>

<ListView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/ingredients_view"
    android:layout_above="@+id/search_button"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_below="@+id/add_button" />

 </RelativeLayout>

自定义适配器IngredientBinAdapter:

public class IngredientBinAdapter extends BaseAdapter {

private Context context = null;
private List<HashMap<String,ImageButton>> items = new ArrayList<>();



public IngredientBinAdapter(Context context, ArrayList<HashMap<String,ImageButton>> items){
    this.context=context;
    this.items=items;
}

@Override
public int getCount() {
    return items.size();
}

@Override
public Object getItem(int position) {
    return items.get(position);
}

@Override
public long getItemId(int position) {
    return getItem(position).hashCode();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if(convertView == null)
        convertView = LayoutInflater.from(context).inflate(R.layout.list_string_button_layout,null);

    HashMap<String,ImageButton> item = (HashMap<String,ImageButton>) getItem(position);
    TextView string = (TextView) convertView.findViewById(R.id.list_item_string);

    String key=(String) item.keySet().toArray()[0];
    string.setText(key);
    item.get(key).setImageResource(R.drawable.ic_delete_black_18dp);


    return convertView;
}
}

Activity:

public class SearchActivity extends AppCompatActivity{

//getting resources and allocating variables
Button add_button = null;
Button search_button = null;
EditText insert_ingredient = null;
ListView ingredient_list_view = null;
ArrayList<HashMap<String,ImageButton>> ingredient_list = new ArrayList<>();
IngredientBinAdapter list_adapter = new IngredientBinAdapter(this,ingredient_list);
ArrayList<String> ingredients_utils = new ArrayList<>();

View.OnClickListener bin_button_listener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        System.out.println("BIN_BUTTON CLICKED");
        ImageButton clicked_button = (ImageButton) v;
        for(Iterator<HashMap<String,ImageButton>> i = ingredient_list.iterator(); i.hasNext(); ){
            HashMap<String,ImageButton> temp= i.next();
            if(temp.values().toArray()[0].equals(clicked_button))
                ingredient_list.remove(temp);
        }
        list_adapter.notifyDataSetChanged();

    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_search);
}

@Override
protected void onStart(){
    super.onStart();

    add_button = (Button) findViewById(R.id.add_button);
    search_button = (Button) findViewById(R.id.search_button2);
    insert_ingredient = (EditText) findViewById(R.id.ingredient_text_input);
    ingredient_list_view = (ListView) findViewById(R.id.ingredients_view);



    ingredient_list_view.setAdapter(list_adapter);

    //add_button listener
    add_button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String current_ingredient_string = insert_ingredient.getText().toString().trim();
            if (!current_ingredient_string.isEmpty() && !ingredients_utils.contains(current_ingredient_string)) {
                HashMap<String, ImageButton> temp = new HashMap<String, ImageButton>();
                ImageButton temp_bin_button = new ImageButton(SearchActivity.this);
                temp_bin_button.setOnClickListener(bin_button_listener);

                temp.put(current_ingredient_string, temp_bin_button);
                ingredient_list.add(temp);

                list_adapter.notifyDataSetChanged();

            }
            ingredients_utils.add(insert_ingredient.getText().toString().trim());
            insert_ingredient.getText().clear();
        }

    });
}
}

首先

  • 您应该将您的逻辑移至 onCreate() 参见:Difference between onCreate() and onStart()?

  • 你应该在适配器的方法中:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    
        // 1. inflate view 
        // 2. find button 
        // 3. assign here listener to bin button 
    
        //  i advice to use convert view pattern 
    
    } 
    

一些提示:

  • 创建描述行项目的数据对象

    public class BinRow {
    
         private String _someString;
         private Drawable _imageDrawable; //  (or resource id name)
    
         public String getString() {
              return _someString;
         }
    
         public Drawable getImage() {
              return _imageDrawable;
        }
    
         public BinRow(String someText, Drawable imageDrawable) {
            _someText = someText; 
            _imageDrawable = imageDrawable;
         }
    
    
    }
    

这里有适配器示例(您需要将 Album - 调整到您的 BinRow 和行布局并在视图持有者中转换视图项目)- 这应该向您展示适配器的工作原理:

public class AlbumAdapter extends BaseAdapter implements IListAdapter<Album> {

    private List<Album> _albums;
    private Context _context;
    private LayoutInflater _layoutInflater;

    static class ViewHolder {
        ImageView imageView;
        TextView albumName;

         public ViewHolder(View v) {
            imageView = (ImageView) v.findViewById(R.id.image);
            albumName = (TextView) v.findViewById(R.id.tvAlbumName);
        }
    }

    public AlbumAdapter(List<Album> albums) {
        if(albums == null) { 
           _albums = new ArrasyList<>();
        } else {
           _albums = albums;
        }
    }

    @Override
    public int getCount() {
         return _albums.size();
    }

    @Override
    public Album getItem(int position) {
          return _albums.get(position);
    }

    @Override
    public long getItemId(int position) {
         return position;
    }

    @Override
    public View getView(int position, View convertView, final ViewGroup parent) {

        final Album album = getItem(position);

        if (_context == null) {
            _context = parent.getContext();
        }

        if (_layoutInflater == null) {
            _layoutInflater = LayoutInflater.from(_context);
        }

        View _view = convertView;

        ViewHolder viewHolder;

        if (_view == null) {
           _view = _layoutInflater.inflate(R.layout.album_item_layout, parent, false);
            viewHolder = new ViewHolder(_view);
            _view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) _view.getTag();
        }

        viewHolder.albumName.setText(album.getAlbumDescription());

        // here u can set:  image to image view & listener to image 
        // image view could be a button 
        viewHolder.imageView.setOnClickListener(View.OnClickListener);

        return _view;
     }



    @Override
    public void add(Album listElement) {
        _albums.add(listElement);
    }

    @Override
    public void addAll(List<Album> listOfElements) {
        _albums.addAll(listOfElements);
    }

    @Override
    public void clear() {
        _albums.clear();
    }

    @Override
    public void remove(Album listElement) {
        _albums.remove(listElement);
    }
}

public interface IListAdapter<T> {
    void add(T listElement);
    void addAll(List<T> listOfElements);
    void clear();
    void remove(T listElement);
}
  • 以上接口作为适配器列表方法的助手