SimpleAdapter.ViewBinder方法說明

來源:互聯網
上載者:User

SimpleAdapter,跟名字一樣,一個簡單的適配器,既為簡單,就只是被設計來做簡單的應用的,比如待用資料的綁定,不過仍然有自訂的空間,比如說在每一個ListItem中加一個按鈕並添加響應事件.首先還是先看一下SimpleAdapter的定義吧,直接翻譯下SDK doc 吧:

  這是一個簡單的適配器,可以將待用資料映射到XML檔案中定義好的視圖。你可以指定由Map組成的List(比如ArrayList)類型的資料。在ArrayList中的每個條目對應List中的一行。Maps包含每一行的資料。你可以指定一個XML布局以指定每一行的視圖,根據Map中的資料對應關鍵字到指定的視圖。綁定資料到視圖分兩個階段,首先,如果設定了SimpleAdapter.ViewBinder,那麼這個設定的ViewBinder的setViewValue(android.view.View, Object, String)將被調用。如果setViewValue的傳回值是true,則表示綁定已經完成,將不再調用系統預設的綁定實現。如果傳回值為false,視圖將按以下順序綁定資料:
  • 如果View實現了Checkable(例如CheckBox),期望綁定值是一個布爾類型。
  • TextView.期望綁定值是一個字串類型,通過調用setViewText(TextView, String)綁定。
  • ImageView,期望綁定值是一個資源id或者一個字串,通過調用setViewImage(ImageView,
    int) 或 setViewImage(ImageView, String)綁定資料。
  如果沒有一個合適的綁定發生將會拋出IllegalStateException。

   先看一下建構函式:

  

public SimpleAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)

參數

  context  SimpleAdapter關聯的View的運行環境

  data    一個Map組成的List。在列表中的每個條目對應列表中的一行,每一個map中應該包含所有在from參數中指定的鍵

  resource   一個定義清單項目的布局檔案的資源ID。布局檔案將至少應包含那些在to中定義了的ID

  from         一個將被添加到Map映射上的鍵名

  to     將綁定資料的視圖的ID,跟from參數對應,這些應該全是TextView

  舉個例子:

public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        ListView lv = (ListView) findViewById(R.id.listView1);        String[] from = { "Text", "Button" };        int[] to = { R.id.text, R.id.button };        List<Map<String, ?>> list = new ArrayList<Map<String, ?>>();        for (int i = 0; i < 10; i++) {            Map<String, String> m = new HashMap<String, String>();            m.put("Text", "Text" + i);            m.put("Button", "Button" + i);            list.add(m);        }        SimpleAdapter adapter = new SimpleAdapter(this, list, R.layout.listitem, from, to);        lv.setAdapter(adapter);}

listitem.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="horizontal" >    <TextView        android:layout_width="wrap_content"        android:id="@+id/text"        android:layout_height="wrap_content"        android:layout_weight="1" />    <Button        android:id="@+id/button"        android:layout_width="wrap_content"        android:layout_height="wrap_content" /></LinearLayout>

  ListView中的每一項都包含一個TextView跟一個Button,在SimpleAdapter的建構函式中,我們指定了要繫結資料:list, list是一個由Map組成的ArrayList, Map的作用就是連同後面的from, to參數定義資料是如何綁定的,在上面的例子中

String[] from = { "Text", "Button" };int[] to = { R.id.text, R.id.button };

  而在for迴圈中每個map都put進了兩個索引值對,鍵名跟from中定義的一一對應,這就表示對於ListView中的每一項,依次尋找在to參數中定義的資源ID,根據這個資源ID在to參數數組中的位置,找到from參數中對應位置的值,以這個值為鍵,在list中的相應項(一個Map)中以這個值為鍵取出這個鍵對應的值綁定到這個資源ID對應的視圖中.

  在上面的例子中每一個ListItem都包含一個TextView與一個Button,但程式運行起來後會發現,按鈕可以點擊,而ListItem卻無法點擊,而且沒有對每一個Button關聯響應事件,ListItem無法點擊是因為按鈕搶佔了ListItem的焦點,在listitem.xml而已檔案中對LinearLayout加上一個屬性就可解決問題:

    android:descendantFocusability="blocksDescendants"

  下面的問題就是Button的響應事件了.

  我的們下SimpleAdaper的源碼會發現,資料的綁定是能過一個叫bindView的函數實現的

   private void bindView(int position, View view) {        final Map dataSet = mData.get(position);        if (dataSet == null) {            return;        }        final ViewBinder binder = mViewBinder;        final String[] from = mFrom;        final int[] to = mTo;        final int count = to.length;        for (int i = 0; i < count; i++) {            final View v = view.findViewById(to[i]);            if (v != null) {                final Object data = http://www.cnblogs.com/angeldevil/archive/2012/04/05/dataSet.get(from[i]);                String text = data =http://www.cnblogs.com/angeldevil/archive/2012/04/05/= null ? "" : data.toString();                if (text == null) {                    text = "";                }                boolean bound = false;                if (binder != null) {                    bound = binder.setViewValue(v, data, text);                }                if (!bound) {                    if (v instanceof Checkable) {                        if (data instanceof Boolean) {                            ((Checkable) v).setChecked((Boolean) data);                        } else if (v instanceof TextView) {                            // Note: keep the instanceof TextView check at the bottom of these                            // ifs since a lot of views are TextViews (e.g. CheckBoxes).                            setViewText((TextView) v, text);                        } else {                            throw new IllegalStateException(v.getClass().getName() +                                    " should be bound to a Boolean, not a " +                                    (data =http://www.cnblogs.com/angeldevil/archive/2012/04/05/= null ? "<unknown type>" : data.getClass()));                        }                    } else if (v instanceof TextView) {                        // Note: keep the instanceof TextView check at the bottom of these                        // ifs since a lot of views are TextViews (e.g. CheckBoxes).                        setViewText((TextView) v, text);                    } else if (v instanceof ImageView) {                        if (data instanceof Integer) {                            setViewImage((ImageView) v, (Integer) data);                                                    } else {                            setViewImage((ImageView) v, text);                        }                    } else {                        throw new IllegalStateException(v.getClass().getName() + " is not a " +                                " view that can be bounds by this SimpleAdapter");                    }                }            }        }    }

  其流程大致是,首先檢查SimpleAdapter有沒有指定SimpleAdapter.ViewBinder,如果指定了就調用其setViewValue方法, SimpleAdapter.ViewBinder是一個介面,也只有這一個方法,如果ViewBinder返回true表示我們已經完成了對這個View的資料繫結,就不再調用系統預設的實現,當然我們也可以設定一個ViewBinder添加一些功能後通過返回false再讓系統綁定資料,比如對按鈕添加響應事件,而按鈕上的文字由預設實現綁定.通過看bindView的實現就可以明白開始時所說的綁定順序了:Checkable,TextView,ImageView.

  我們對ListItem的自訂是通過對SimpleAdapter設定ViewBinder來實現的

        SimpleAdapter.ViewBinder binder = new SimpleAdapter.ViewBinder() {            @Override            public boolean setViewValue(View view, Object data, String textRepresentation) {                if (view instanceof Button) {                    final View button = view;//                    button.setBackgroundDrawable(getResources().getDrawable(R.drawable.ic_launcher));                    view.setOnClickListener(new OnClickListener() {                        LinearLayout listItem = (LinearLayout) button.getParent();                        TextView tv = (TextView) listItem.findViewById(R.id.text);                        @Override                        public void onClick(View v) {                            Toast.makeText(AdapterDemoActivity.this, tv.getText(), Toast.LENGTH_SHORT).show();                        }                    });                    return false;                }                return false;            }        };        adapter.setViewBinder(binder);

  系統對每一個view調用binder的setViewValue(此例中是R.id.text和R.id.button,一個TextView與一個Button),我們首先檢測這個view是不是一個Button,如果是的話就關聯點擊事件,可能通過getParent()函數取得parentView以找到這個view的兄弟view,比如這個例子中的實現就是點擊Button後輸出這個Button所在的ListItem中的TextView上的文字.

  在setViewValue中可以完全自訂我們的實現,比如在Button後加一個TextView,當然可以加任何View,但這樣做沒任何意義,當你需要這樣做時你不需要用SimpleAdater而應該用BaseAdapter:

        SimpleAdapter.ViewBinder binder = new SimpleAdapter.ViewBinder() {            @Override            public boolean setViewValue(View view, Object data, String textRepresentation) {                if (view instanceof Button) {                    final View button = view;                    LinearLayout listItem = (LinearLayout) button.getParent();                    TextView textView = new TextView(AdapterDemoActivity.this);                    textView.setText("AA");                    listItem.addView(textView,new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));                    return false;                }                return false;            }        };        adapter.setViewBinder(binder);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.