原地址:http://blog.csdn.net/sahadev_/article/details/49464273
有时候我们会有这么一个需求,在Listview的某个Item上有个按钮,点击这个按钮之后呢,需要对其它的item做一些操作,就像下面这个:
采纳按钮点击之前:采纳按钮点击之后:
简单介绍一下这两张图的意思:
模拟了一个Listview,在每个Item上都有一个“采纳”按钮,当点击其中一个“采纳”之后,需要将其它“采纳”按钮隐藏,并且自身需要改为“已采纳”,如后面的图所示。
我们有一种简单的办法可以做到,就是更改数据的值,并且让Adapter重新刷新一遍,这是一种简单粗暴的方式,用户体验非常不好,会使整个页面都闪一下。
那么为了有没有什么更好的办法呢?有的,使用我们的观察者模式。
观察者模式在我们这里的基本实现方式是:当其中一个按钮被点击之后,通过回调更新其它控件即可。如何实现呢?以简单代码来说明:
- package com.sahadev;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.Set;
- import android.annotation.SuppressLint;
- import android.app.Activity;
- import android.content.Context;
- import android.os.Bundle;
- import android.os.Message;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.Button;
- import android.widget.ListView;
- import com.lidroid.xutils.ViewUtils;
- import com.lidroid.xutils.view.annotation.ViewInject;
- import com.sahadev.renren.R;
- public class MainActivity extends Activity {
- @ViewInject(R.id.listview)
- private ListView listview;
- private BaseAdapter internalAdapter;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_zoom);
- ViewUtils.inject(this);
- internalAdapter = new InternalAdapter(this);
- listview.setAdapter(internalAdapter);
- }
- /**
- * 观察者模式的回调接口
- *
- * @author Sahadev
- *
- */
- public interface Callback {
- public void update(Message msg);
- }
- private static class InternalAdapter extends BaseAdapter {
- private int dataSize = 6;
- private Map<View, Callback> maps;
- private LayoutInflater inflate;
- public InternalAdapter(Context context) {
- super();
- inflate = LayoutInflater.from(context);
- maps = new HashMap<View, MainActivity2.Callback>();
- }
- @Override
- public int getCount() {
- return dataSize;
- }
- @Override
- public Object getItem(int position) {
- return null;
- }
- @Override
- public long getItemId(int position) {
- return 0;
- }
- @SuppressLint("InflateParams")
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = inflate.inflate(R.layout.listview_item_layout, null);
- Button button = (Button) convertView.findViewById(R.id.button);
- // 生成一个观察者
- Callback callback = new Callback() {
- @Override
- public void update(Message msg) {
- // 当其中一个按钮被点击时通过调用update方法来更新其它UI
- // 先隐藏所有的采纳按钮
- View view = (View) msg.obj;
- if (msg.what == 0) {
- view.setVisibility(View.INVISIBLE);
- } else {
- Button button = (Button) view;
- button.setText("已采纳");
- button.setEnabled(false);
- }
- }
- };
- // 将我们的需要更改的对象和观察者一并放入maps
- maps.put(button, callback);
- button.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(final View v) {
- // 遍历maps中所有的监听者
- Set<Entry<View, Callback>> entrySet = maps.entrySet();
- Iterator<Entry<View, Callback>> iterator = entrySet.iterator();
- while (iterator.hasNext()) {
- Entry<View, Callback> next = iterator.next();
- // 使用value的update方法将key作为参数使得监听的地方对它进行修改
- Message msg = new Message();
- View temp = next.getKey();
- msg.obj = temp;
- if (temp.equals(v) || temp == v) {// 如果是点击的按钮本身,则需要对它进行特殊处理
- msg.what = 1;
- }
- // 通知所有的观察者
- next.getValue().update(msg);
- }
- }
- });
- }
- return convertView;
- }
- }
- }