Android ListView

本文包含:
一、一般的listview(系统自定义样式)
二、自定义Listview

一、一般Listview

实例效果:

  1. 下方EditText回车则添加到ListView
  2. 点击ListView中某item直接删除该Item

ListView属性

属性解释
android:entries=”@array/listViewNameArray”指定数据
android:divider=”@color/colorAccent”分隔符颜色
android:choiceMode=”singleChoice”选择模式(单选、多选)

1、最简单实例

  • 通过android:entries="@array/listViewNameArray"指定内容
  • "@array/listViewNameArray"valueString中的String-array(string数组)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.feather.androiddemos.ListViewActivity"
    android:orientation="vertical">

    <ListView
        android:entries="@array/listViewNameArray"
        android:divider="@color/colorAccent"
        android:choiceMode="singleChoice"
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </ListView>

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10pt"
        android:hint="输入内容进行添加"/>

</LinearLayout>

2、通过ArrayAdapter设置ListView

        //string 数组
        String arrays[] = {"nanjing", "beijing", "nantong", "shanghai", "chongqing"};

        //初始化适配器
        ArrayAdapter adapter = new ArrayAdapter<String>(this,  //context
                        android.R.layout.simple_spinner_item,  //布局:使用系统自带文字布局
                                                      arrays); //string数组
        //获得控件ListView
        listView = (ListView) findViewById(R.id.listView);

        //设置适配器
        listView.setAdapter(adapter);

可以使用系统专门给listview提供的布局

如:
1. simple_list_item_1
2. simple_list_item_single_choice 有单选框

3、在ListActivity中使用ListView

xml布局文件

  • ListView的ID必须为@android:id/list
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.feather.androiddemos.ListViewActivity"
    android:orientation="vertical">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10pt"
        android:layout_alignParentBottom="true"
        android:hint="输入内容进行添加"/>

    <ListView
        android:id="@android:id/list"
        android:entries="@array/listViewNameArray"
        android:divider="@color/colorAccent"
        android:choiceMode="singleChoice"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/editText">

    </ListView>

</RelativeLayout>

Java

  1. 继承ListActivity
  2. 设置适配器
        //string 数组
        String arrays[] = {"nanjing", "beijing", "nantong", "shanghai"};

        //初始化适配器
        ArrayAdapter adapter = new ArrayAdapter<String>(this,  //context
                        android.R.layout.simple_list_item_1,  //布局:使用系统自带文字布局
                                                      arrays); //string数组
        //设置适配器
        this.setListAdapter(adapter);
  1. 获得listview方法并且进行监听
listView = getListView();            //获得ListView
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

      }
});

4、通过EditText输入并添加listview的item

  • 通过ListActivity实现
public class ListViewActivity extends ListActivity {

    ListView listView = null;
    ArrayList<String> listItems = null;
    EditText editText = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view);

        editText = (EditText) findViewById(R.id.editText);


        listItems = new ArrayList<>();
        //初始化适配器
        final ArrayAdapter adapter = new ArrayAdapter<String>(this,  //context
                        android.R.layout.simple_list_item_1,  //布局:使用系统自带文字布局
                            listItems); //数据链表

        this.setListAdapter(adapter);

        listView = getListView();            //获得ListView
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(ListViewActivity.this, "当前点击的Item:"+position, Toast.LENGTH_SHORT).show();
            }
        });

        //EditText监听器
        editText.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                //输入Enter并且松开
                if(keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP)
                {
                    listItems.add(editText.getText().toString()); 
                    adapter.notifyDataSetChanged();//通知数据发生改变
                    editText.setText(null);
                }
                return false;
            }
        });
    }
}

观察者模式

又被称为“发布订阅模式”

自定义ListView

步骤:

  1. xml布局文件(包含listview)
  2. 适配器java代码(用于如何自定义Listview)
    这里继承了 ArrayAdapter<ReadingItem>适配器,记得构造函数中传入自定义对象 ReadingItem的链表。
public class ReadingAdapater extends ArrayAdapter<ReadingItem>{

    int resource_id;
    ReadingQuestion readingQuestion;
    QuestionReadingActivity activity;

//记得要有`List<ReadingItem> objects`
    public ReadingAdapater(Context context, int resource, List<ReadingItem> objects, ReadingQuestion readingQuestion, QuestionReadingActivity activity) {
        super(context, resource, objects);

        this.resource_id = resource;
        this.readingQuestion = readingQuestion; //传入的一些自定义对象
        this.activity = activity;
    }


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

        //获得具体对象(构造器传入的链表:objects)
        readingItem = getItem(position);

        if(convertView == null){
            convertView = LayoutInflater.from(getContext()).inflate(resource_id, null);

            /*---------------------*/
            /*  这里进行自定义     */
            /*---------------------*/
        }
        return convertView;
    }
  1. 使用
//获得ListView
ListView listView = (ListView) view.findViewById(R.id.reading_item_list);
//新建适配器对象
readingAdapater = new ReadingAdapater(QuestionReadingActivity.this, R.layout.question__item,
                    lists, //传入数据的链表
                    readingQuestion,
                    this);

//设置适配器
listView.setAdapter(readingAdapater);

//这里是Listview只显示一行时的解决办法,具体见错误汇总1.
fixListViewHeight(listView);

三、知识点汇总

小的知识点,记录下来,以备将来用。

如何让listview滚动到底部 ?

方法一:

msgListViewListView控件
adapterListView绑定的Adapter,如果不方便直接使用,也可以通过ListViewgetAdapter()方法获取到,前提是你已经绑定了适配器哦
里面的参数就很熟悉了吧,其实这个方法的主要作用是选中listview的指定列,选中了,自然就得让这个item可见,自然就滚动咯

msgListView.setSelection(adapter.getCount()-1);  

方法二:

这个就比较直接了

msgListView.setSelection(msgListView.getBottom()); 

四、错误汇总

1.ListView只显示一行

在代码正确时,发现实际效果Listview只有一行,这是因为Listview嵌套在ScrollView中,会导致无法正确计算ListView的大小。

解决方案如下:
链接:http://www.cnblogs.com/exmyth/p/4544551.html

方案1:去除ScrollView
方案2:在代码中,根据Listview的列表子项计算列表高度
listView = (ListView) findViewById(R.id.test_listView);   

//适配器
listView.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,adapterData));   

//计算高度
fixListViewHeight(listView);   
public void fixListViewHeight(ListView listView) {   

        // 如果没有设置数据适配器,则ListView没有子项,返回。  

        ListAdapter listAdapter = listView.getAdapter();  

        if (listAdapter == null) {   
            return;   
        }   

        int totalHeight = 0; 
        for (int index = 0, len = listAdapter.getCount(); i < len; i++) {     

            View listViewItem = listAdapter.getView(index , null, listView);  

            // 计算子项View 的宽高   
            listViewItem.measure(0, 0);    
            // 计算所有子项的高度和
            totalHeight += listViewItem.getMeasuredHeight();    
        }   

        ViewGroup.LayoutParams params = listView.getLayoutParams();   

        // listView.getDividerHeight()获取子项间分隔符的高度   
        // params.height设置ListView完全显示需要的高度
        params.height = totalHeight+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));   
        listView.setLayoutParams(params);   

    }   

2. notifyDataSetChanged()无效

情况一:数据库查询出ListView设置后不刷新

转载:

关于ListView中notifyDataSetChanged()刷新数据不更新原因 .

使用Listview的时候: 当要动态显示更改后的数据(例如数据库改动), 很多人应该都用过notifyDataSetChanged();这个方法来刷新Listview,显示改后的数据.

这时候就要注意了:

                 ...... 
private ArrayList<HashMap<String, Object>> usersList; 
...... 
usersList= query(......);     //根据查询函数获取一个ArrayList并赋值给绑定到Adapter的数据源usersList 
sAdapter.notifyDataSetChanged(); 
...... 

如果你也是: 上面这种形式去刷新ListView的数据的话, 是不可以更新的. 必须改成如下形式:


...... 
//usersList= query(......);    
usersList.clear();  
usersList.addAll(query(......)); 
sAdapter.notifyDataSetChanged(); 

原因是:

sAdapter会通过usersList获取List中的内容。但是实际上可能(也应该)是,在调用super(MyActivity.this, R.layout.item, usersList)时sAdapter保存了usersList指向原List(假设为List a)的引用,在调用query函数之后,usersList指向了一个新的List(List b)。但是在调用notifyDataSetChanged()时,sAdapter会跟据保存的引用(即指向List a的引用)去更新,因此当然还是原来的结果,不会进行更新。

如果大家也出现这种情况可以使用后者去刷新ListView, 应该就没问题了


情况二:多个线程里面ListView不刷新

只需要在UI线程执行notifyDataSetChanged()即可
代码如下:

runOnUiThread(new Runnable() {
        @Override
        public void run() {
            chatItemList.add(new ChatItem("test123", R.drawable.feather, "帅猎羽", msg, dateString));
            adapter.notifyDataSetChanged();
        }
});
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值