ListView的创建及遇到的问题

     我要总结一下关于ListView(用于垂直显示的列表控件的问题,这是我创建android控件中遇到的最难的一个,同时老师给的代码一堆坑,只能不断自己搜资料解决问题,花了一堆时间才大致理清ListView,累的不行。

运行结果图:


      贴上源码:

      这是activity_main.xml的代码:

<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.test43.MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <ListView
        android:id="@+id/android:list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_marginBottom="22dp"
        android:drawSelectorOnTop="false"
        android:scrollbars="vertical" >
    </ListView>

</RelativeLayout>

        这是List使用的布局文件user.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"
    	android:paddingLeft="10dip"
    	android:paddingTop="10dip"
    	android:paddingRight="10dip">
	<TextView 
	    android:id="@+id/user_name"
	    android:layout_width="250dip"
	    android:layout_height="wrap_content"
	    android:singleLine="true"
	    android:textSize="10pt"
	    android:gravity="left"/>
	<TextView 
	    android:id="@+id/user_ip"
	    android:layout_width="50dip"
	    android:layout_height="wrap_content"
	    android:singleLine="true"
	    android:textSize="10pt"
	    android:gravity="center"/>
</LinearLayout>

        这是MainActivity.java的代码:

package com.example.test43;

import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class MainActivity extends ListActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		
                //数据源部分
                ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();   
                HashMap<String, String> map1 = new HashMap<String, String>();
                HashMap<String, String> map2 = new HashMap<String, String>();
                HashMap<String, String> map3 = new HashMap<String, String>();
                map1.put("user_name", "张三");
                map1.put("user_ip", "192.168.0.1");
                map2.put("user_name", "李四");
                map2.put("user_ip", "192.168.0.1");
                map3.put("user_name", "王五");
                map3.put("user_ip", "192.168.0.1");
                list.add(map1);
                list.add(map2);
                list.add(map3);
        
                
    		ListView listView=(ListView)findViewById(android.R.id.list);
                registerForContextMenu(listView);                            //注册上下文菜单

                SimpleAdapter listAdapter = new SimpleAdapter(this, list, R.layout.user, new String[]{"user_name","user_ip"},
 new int[]{R.id.user_name,R.id.user_ip});                         //新建适配器并添加数据源到适配器
                setListAdapter(listAdapter);                      //视图加载适配器,将SimpleAdapter设置给当前的ListActivity
	        }


     //添加点击事件监听,获取选中项的值
     @Override
     protected void onListItemClick(ListView l, View v, int position, long id) {
		// TODO Auto-generated method stub
		super.onListItemClick(l, v, position, id);
		System.out.println("id--------------"+id);
		System.out.println("position--------"+position);
}


     public void onCreateContextMenu(ContextMenu menu,View
	 		v,ContextMenuInfo menuInfo){
	    	menu.setHeaderTitle("选项");
	    	menu.add(0, 1, 1, "删除");
	    	menu.add(0, 2, 3, "编辑");
	    	super.onCreateContextMenu(menu, v, menuInfo);}
     //菜单单击响应
     @Override
     public boolean onContextItemSelected(MenuItem item){
	      return true;}

    
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}
}

       总结:

       1.java当中有个ListView的事件监听器的问题:

       我们所定义的Activity 要继承ListActivity,它是Activity的子类

       原因是:onListItemClick方法是ListActivity才有的方法,在Activity中是无效的

扫描二维码关注公众号,回复: 1482928 查看本文章

       解决方法是:方法一、继承ListActivity就可直接使用 protected void onListItemClick(ListView l, View v, int position, long id){ }就有了添加事件监听器的相关操作。

方法二、如果你非要继承Activity,代码就要改成:仍然有两种方法给ListView来setOnItemClickListener

方法1.让你的Activity实现OnItemClickListener接口(Implement OnItemClickListener to your Activity),并将onListItemClick()方法变为onItemClick()方法

代码示例:

public class MyActivity extends Activity implements OnItemClickListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

    }
}

方法2.将onListItemClick方法换成mListView.setOnItemClickListener

代码示例:

mListView.setOnItemClickListener(new OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    }
});

参考链接:The method onListItemClick(ListView, View, int, long) of type MainActivity must override or implement a supertype method(来自Stack Overflow)

       2.ListView使用了适配器SimpleAdapter 

         适配器(Adapter)一般是为ListView提供数据的转换,当然GridView[网格视图]、Spinner[下拉列表]、Gallery[画廊]、ViewPage等都需要使用适配器来为其设置数据源。Android项目中一般使用BaseAdapter、SimpleAdapter和ArrayAdapter三种适配器。

         适配器是把数据变成符合界面风格的形式,并且通过ListView显示出来,也就是说适配器是数据和界面之间的桥梁。适配器在数据库中的数据(后台)和显示页面(前端)中充当一个转换器的角色,数据库中的数据(如数组,链表,数据库,集合等)通过适配器变成手机页面能够正常显示的数据。可以看作是界面数据绑定的一种理解。假设把数据、适配器和ListView(页面)比喻成一个MVC模式的话,那么适配器(Adapter)在这中间就充当了Controller的角色。

         参考链接:1.适配器功能的图片理解

                         2.Android应用项目中BaseAdapter、SimpleAdapter和ArrayAdapter中的三种适配器

                         3.SimpleAdapter 的用法及点击事件中如何获取选中项的值

       3.关于数据源的问题

          适配器(Adapter)是给ListView界面绑定数据的,而这数据源的编写方法也有多种。

         (1)直接写在protected void onCreate(Bundle savedInstanceState) {}中,如我们本例中的一样

         (2)单独写一个数据源的getdata()方法,返回数据源list(新建自定义List<Map<String,Object>> dataList,并通过方法返回到适配器中)

                 代码示例:      

package com.example.administrator.mydivlistview;  
  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.AdapterView;  
import android.widget.ListView;  
import android.widget.SimpleAdapter;  
import android.widget.TextView;  
import android.widget.Toast;  
  
import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  
  
  
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener{  
    private ListView listview;  
    private SimpleAdapter sim_adapter;  
    private TextView text;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.layout);  
        text=(TextView) findViewById(R.id.text);  
        listview = (ListView) findViewById(R.id.listview);  
        sim_adapter = new SimpleAdapter(this, getdata(), R.layout.item, new String[]{"pic", "text"}, new int[]{R.id.pic, R.id.text});  
        listview.setAdapter(sim_adapter);  
        listview.setOnItemClickListener(this);  
    }  
  
    private List<Map<String, Object>> getdata() {  
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();  
        Map<String, Object> map = new HashMap<String, Object>();  
        map.put("pic", R.drawable.apple_pic);  
        map.put("text", "apple");  
        list.add(map);  
        map = new HashMap<String, Object>();  
        map.put("pic", R.drawable.pear_pic);  
        map.put("text", "pear");  
        list.add(map);  
        map = new HashMap<String, Object>();  
        map.put("pic", R.drawable.watermelon_pic);  
        map.put("text", "watermelon");  
        list.add(map);  
        map = new HashMap<String, Object>();  
        map.put("pic", R.drawable.cherry_pic);  
        map.put("text", "cherry");  
        list.add(map);  
        map = new HashMap<String, Object>();  
        map.put("pic", R.drawable.strawberry_pic);  
        map.put("text", "strawberry");  
        list.add(map);  
        map = new HashMap<String, Object>();  
        map.put("pic", R.drawable.grape_pic);  
        map.put("text", "grape");  
        list.add(map);  
        map = new HashMap<String, Object>();  
        map.put("pic", R.drawable.orange_pic);  
        map.put("text", "orange");  
        list.add(map);  
        map = new HashMap<String, Object>();  
        map.put("pic", R.drawable.mango_pic);  
        map.put("text", "mango");  
        list.add(map);  
        map = new HashMap<String, Object>();  
        map.put("pic", R.drawable.pineapple_pic);  
        map.put("text", "pineapple");  
        list.add(map);  
        map = new HashMap<String, Object>();  
        map.put("pic", R.drawable.banana_pic);  
        map.put("text", "banana");  
        list.add(map);  
        return list;  
    }  
  
    @Override  
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {  
        /*adapterView是指当前的listview; 
         *view是当前listview中的item的view的布局,就是可用这个view获取里面控件id后操作控件 
         * i是当前item在listview中适配器的位置 
         * l是当前item在listview里第几行的位置 
         */  
        //获得选中项中的HashMap对象  
        HashMap<String,String> map=(HashMap<String,String>)adapterView.getItemAtPosition(i);  
        String Text=map.get("text");  
        Toast.makeText(MainActivity.this,Text,Toast.LENGTH_SHORT).show();  
    }  
}  
        4.因为使用了上下文,所以有涉及上下文的方法

    项目的文件结构:



        创建ListView过程中遇到的问题:

        1、在AVD上打开app时,会提示"unfortunately ,项目名 has stopped"

          解决办法:我遇到的情况是刚好在logcat下面显示了错误信息:"Your content must have a ListView whose id attribute is android.R.id.list",然后就去解决这个问题。通过搜索资料得知:应将main.xml中的<ListView>标签中的ListView的ID由android:id="@+id/list"(通过控件生成ListView时自动生成的语句)改为android:id="@id/android:list"。这时main.java中的ListView listView=(ListView)findViewById(R.id.list);语句就会报错,需将参数改为android.R.id.list即可。


       2、工程内容没有错误,但是工程图标却有红叉  或者运行时显示:Your project contain errors,please fix them before running your application

     (1)我的情况是控制台(console)提示: [2018-04-12 21:28:49 - Dex Loader] Failed to load D:\Program Files\study\Android SDK\android-sdk-windows\build-tools\27.0.3\lib\dx.jar

[2018-04-12 21:28:49 - test49] Unknown error: Unable to build: the file dx.jar was not loaded from the SDK folder!

          问题产生的原因是:Android SDK Build-tools的版本已经高于Android SDK Platform-tools版本了

       解决办法是:方法一:找到你的sdk安装位置(我的是:D:\Program Files\study\Android SDK\android-sdk-windows\build-tools),找到build-tools下面你安装的build-tools版本,选择一个以往的版本,然后在安卓工程中打开project-properties文件,在里面添上一句: sdk.buildtools=25.0.0。该方法的参考链接是:解决Unknown error: Unable to build: the file dx.jar was not loaded from the SDK folder!


方法二:在你安装sdk的目录下找到你安装的build-tools(我的是D:\Program Files\study\Android SDK\android-sdk-windows\build-tools),将老版本build-tool的lib文件夹下的dx.jar(我的是\25.0.0\lib\dx.jar)替换新版本的build-tool的dx.jar。该方法的参考链接:关于解决Eclipse报错显示Unable to build: the file dx.jar was not loaded from the SDK folder

    (2)如果情况是控制台显示:[2018-04-12 21:25:21 - test49] AndroidManifest.xml file missing!

则对项目右键 ->"Android Tools"->"Fix Project Properties",然后 project clean一下或者重启eclipse

猜你喜欢

转载自blog.csdn.net/adnap7/article/details/79906994