ListView解析

本文用ListView實(shí)現(xiàn)了一個(gè)可以展示文本和圖片的類似聊天消息的界面组砚。包括ListView的優(yōu)化,ListView下拉到底部自動(dòng)刷新以及ListView常用屬性等知識(shí)。主要參考為網(wǎng)易微專業(yè)課程。其中布局文件都已經(jīng)省略。
效果如下:


IMG_20161013_092308.png

創(chuàng)建TextMessage類和ImageMessage類:

public class TextMessage {
    private String text;
    public TextMessage(String content) {
        this.text = content;
    }

    public String getText() {
        return text;
    }
public class ImageMessage {
    private  int imgResId;

    public ImageMessage(int imgResId) {
        this.imgResId = imgResId;
    }

    public int getImgResId() {
        return imgResId;
    }
}

Adapter類

public class MainAdapter extends BaseAdapter {
    private static final int VIEW_TYPE_COUNT = 2;
    private interface ViewType {
        // 必須從0開(kāi)始蒿叠,因?yàn)長(zhǎng)istView內(nèi)部是用一個(gè)數(shù)組維護(hù)ViewType的。
        int TEXT = 0;
        int IMAGE =1;
    }
    private ArrayList<Object> list;
    private Context context;

    public MainAdapter(Context context,ArrayList<Object> list) {
        this.context = context;
        this.list = list;
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(context);
        ViewHolder holder = null;
        // 如果是文本消息
        if (getItemViewType(position) == ViewType.TEXT){
            if (convertView == null){
                holder = new ViewHolder();
                convertView=inflater.inflate(R.layout.text_item,parent,false);
                holder.text = (TextView) convertView.findViewById(R.id.text);
                convertView.setTag(holder);
            }else {
                holder = (ViewHolder) convertView.getTag();
            }
            TextMessage textMessage = (TextMessage) list.get(position);
            holder.text.setText(textMessage.getText());
        }else { //如果是圖片消息蚣常。
            if (convertView==null){
                holder = new ViewHolder();
                convertView = inflater.inflate(R.layout.image_item,parent,false);
                holder.image = (ImageView) convertView.findViewById(R.id.image);
                convertView.setTag(holder);
            }else {
                holder = (ViewHolder) convertView.getTag();
            }

            ImageMessage imageMessage = (ImageMessage) list.get(position);
            holder.image.setImageResource(imageMessage.getImgResId());
        }


        return convertView;
    }

    @Override
    public int getViewTypeCount() {
        return VIEW_TYPE_COUNT ;
    }

    @Override
    public int getItemViewType(int position) {
        if (getItem(position) instanceof TextMessage){
            return ViewType.TEXT;
        }else {
            return ViewType.IMAGE;
        }
    }

    private static class ViewHolder{
        ImageView image;
        TextView text;
    }
}

主界面

public class MainActivity extends AppCompatActivity {
    Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;

        ListView listView = (ListView) findViewById(R.id.list);
        final ArrayList<Object> list = new ArrayList<>();
        // 模擬數(shù)據(jù)市咽。
        for (int i=0; i<100;i++){
            if (i%2==0){
                TextMessage textMessage = new TextMessage("我是文本消息");
                list.add(textMessage);
            }else {
                ImageMessage imageMessage = new ImageMessage(R.drawable.image);
                list.add(imageMessage);
            }
        }
        final MainAdapter adapter = new MainAdapter(context,list);
        listView.setAdapter(adapter);

        // 為L(zhǎng)istView設(shè)置點(diǎn)擊事件
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String str = "item "+ position;
                Toast.makeText(context,str, Toast.LENGTH_SHORT).show();
            }
        });

        // 為L(zhǎng)istView設(shè)置滑動(dòng)監(jiān)聽(tīng)事件
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                Log.d("listener","onScrollStateChange scrollState: " + scrollState);
            }

            @Override
            /**
             * @param firstVisibleItem: the index of the first visible cell (ignore if visibleItemCount == 0)
             * @param visibleItemCount: the number of visible cells
             */
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                // 如果滑到最底部,自動(dòng)加載新數(shù)據(jù)抵蚊。
                if(firstVisibleItem+visibleItemCount == totalItemCount){
                    Toast.makeText(context, "加載新的數(shù)據(jù)", Toast.LENGTH_SHORT).show();
                    for (int i = 0 ; i< 100; i++){
                        TextMessage textMessage = new TextMessage("我是文本消息");
                        list.add(textMessage);
                    }
                    adapter.notifyDataSetChanged();
                }
            }
        });

        // 增加數(shù)據(jù)
        Button add = (Button) findViewById(R.id.add_view);
        add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String time = Calendar.getInstance().getTime().toString();
                list.add(0,new TextMessage(time));
                // 通知adapter刷新數(shù)據(jù)施绎。
                adapter.notifyDataSetChanged();
            }
        });

        // 刪除數(shù)據(jù)
        Button delete = (Button) findViewById(R.id.delete_view);
        delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (list.size() > 0){
                    list.remove(0);
                    adapter.notifyDataSetChanged();
                }
            }
        });

    }
}

補(bǔ)充

  • ListView 可以添加FootView、HeadView和EmptyView贞绳。此時(shí)要注意怎樣才能獲得正確的item(parent.getItemAtPosition(position)).
  • OnScrollListener監(jiān)聽(tīng)ListView三種狀態(tài)谷醉,分別是:
  1. SCROLL_STATE_IDLE = 0, 表示ListView停止滑動(dòng)。
  2. SCROLL_STATE_TOUCH_SCROLL = 1,表示ListView隨手指而滑動(dòng)冈闭。
  3. SCROLL_STATE_FLING = 2,表示手指已經(jīng)離開(kāi)屏幕俱尼,ListView隨慣性而滑動(dòng)。

注意 在ListView中萎攒,如果有一個(gè)focusable屬性為true的控件(例如Button)遇八,會(huì)使onItemClickListenter的點(diǎn)擊事件失效矛绘。通過(guò)以下方法就可以使點(diǎn)擊事件傳遞到子控件上。

  • 在item的根布局里設(shè)置 android:descendantFocusability = "blocksDescendants" 屬性刃永。
  • 在5.0以上的系統(tǒng)货矮,可以設(shè)置 android:touchscreenBlocksFoucus = true 屬性。
  • 在該按鈕里設(shè)置 android:focusable = "false" 屬性斯够。

ListView其他屬性:

  • 設(shè)置分隔條:android:divider = "@android:color/darker_gray"
  • 去除分隔條: android:divider = "@null"
  • 隱藏ListView滾動(dòng)條: android:scrollbars = "none"
  • 取消ListView的點(diǎn)擊效果:
    android:listSelector = "@android:color/transparent"
  • 設(shè)置ListView 顯示在第幾頁(yè):
  listView.setSelection(n); //"n"表示第幾個(gè)item.
  listView.smoothScrollBy(distance,duration);
  listView.smoothScrollByOffset(offset);
  listView.smoothScrollToPosition(index);
  • 動(dòng)態(tài)修改ListView:
  mData.add(newData);
  mAdapter.notifyDataSetChanged();
  • 設(shè)置ListView頂部和底部滑動(dòng)背景拉伸效果:
android:overScrollHeader = "@android:coloer/red"  
android:overScrollFooter = "@android:coloer/red"  
  • 設(shè)置ListView頂部和底部漸變效果:
android:requireFadingEade = "vertical"  
android:fadingEdgeLength = "100dp"  
  • 設(shè)置ListView從底部開(kāi)始布局:
    android:stackFromBottom = "true"
  • 設(shè)置ListView增加消息自動(dòng)滾動(dòng)到底部:
    android:transcriptMode = "alwaysSrcoll"

源碼地址.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末囚玫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子读规,更是在濱河造成了極大的恐慌劫灶,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掖桦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡供汛,警方通過(guò)查閱死者的電腦和手機(jī)枪汪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)怔昨,“玉大人雀久,你說(shuō)我怎么就攤上這事〕靡ǎ” “怎么了赖捌?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)矮烹。 經(jīng)常有香客問(wèn)我越庇,道長(zhǎng),這世上最難降的妖魔是什么奉狈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任卤唉,我火速辦了婚禮,結(jié)果婚禮上仁期,老公的妹妹穿的比我還像新娘。我一直安慰自己跛蛋,他們只是感情好熬的,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著赊级,像睡著了一般押框。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上此衅,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天强戴,我揣著相機(jī)與錄音亭螟,去河邊找鬼。 笑死骑歹,一個(gè)胖子當(dāng)著我的面吹牛预烙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播道媚,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼扁掸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了最域?” 一聲冷哼從身側(cè)響起谴分,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎镀脂,沒(méi)想到半個(gè)月后牺蹄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡薄翅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年沙兰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翘魄。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鼎天,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出暑竟,到底是詐尸還是另有隱情斋射,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布但荤,位于F島的核電站罗岖,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏腹躁。R本人自食惡果不足惜呀闻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望潜慎。 院中可真熱鬧捡多,春花似錦、人聲如沸铐炫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)倒信。三九已至科贬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背榜掌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工优妙, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人憎账。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓套硼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親胞皱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子邪意,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容