zoukankan      html  css  js  c++  java
  • android学习8(ListView高级使用)

          ListView在android更开放的,于是继续ListView说明使用。

    首先创建一个android项目,项目名为ListViewTest.

    ListView的简单使用

    改动布局文件,改动后代码例如以下:

    <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"
         >
    
        <ListView 
            android:id="@+id/list_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            ></ListView>
    
    </LinearLayout>
    


    改动MainActivity的代码:

    package com.wj.listviewtest;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    public class MainActivity extends Activity {
    
    	private String [] data={"apple","banana","orange",
    			"watermelon","pear","grape","pineapple","strawberry",
    			"cherry","mango"};
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		//创建适配器
    		ArrayAdapter<String> adapter=new ArrayAdapter<String>(
    				MainActivity.this,android.R.layout.simple_list_item_1,
    				data);
    		ListView listView=(ListView) findViewById(R.id.list_view);
    		listView.setAdapter(adapter);
    	}
    
    	@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;
    	}
    
    }
    


    执行程序结果例如以下:



    ListView是用于显示大量数据的。这些数据我们能够事先准备好。也能够从网上或者数据中中读取。

    android.R.layout.simple_list_item_1是作为ListView子项布局的id。这是android内置的布局文件中面仅仅有一个TextView,可用于简单地显示一段文本。


    2.定制ListView的界面

    首先准备一组图片。分别相应上面提供的水果。

    接着定义一个实体类。作为ListView适配器的适配类型,新建Fruit类。代码例如以下:

    package com.wj.listviewtest;
    
    public class Fruit {
    
    	private String name;//水果名
    	private int imageId;//水果图片的资源id
    	
    	//无參构造函数
    	public Fruit(){}
    	//有參构造函数
    	public Fruit(String name,int imageId){
    		this.name=name;
    		this.imageId=imageId;
    	}
    	
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getImageId() {
    		return imageId;
    	}
    	public void setImageId(int imageId) {
    		this.imageId = imageId;
    	}
    	
    }
    

    Fruit类中仅仅有2个字段,name表示水果的名字,imageId表示水果相应图片的资源id,然后须要为ListView的子项指定一个我们自己定义的布局。在layout文件夹以下新建fruit_item.xml代码例如以下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <ImageView 
            android:id="@+id/fruit_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
    
        <TextView 
            android:id="@+id/fruit_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="10dip"
            />
        
    </LinearLayout>
    


    这个布局中我们定义了一个ImageView用于显示水果的图片,又定义了一个TextView用于显示水果的名称。

    接着我们要创建一个自己定义的适配器,这个适配器继承自ArrayAdapter。并将泛型指定为Fruit。

    新建一个类FruitAdapter代码例如以下:

    package com.wj.listviewtest;
    
    import java.util.List;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    public class FruitAdapter extends ArrayAdapter<Fruit> {
    
    	private int resourceId;
    	public FruitAdapter(Context context, int textViewResourceId,
    			List<Fruit> objects) {
    		super(context, textViewResourceId, objects);
    		// TODO Auto-generated constructor stub
    		/*
    		 * 重写了父类的构造函数,用于将上下文,ListView子项布局的id和数据都传进来。

    * */ resourceId=textViewResourceId; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub //return super.getView(position, convertView, parent); /* * 重写getView方法,这种方法在每一个子项被滚动到屏幕内的时候会被调用。在getView方法中 * ,首先通过getItem方法得到当前项的Fruit实例,然后使用LayoutInflater来为这个子项载入 * 我们传入的布局,接着调用View的findViewById方法分别获取到ImageView和TextView的实例, * 并分别调用他们的setImageResource和setText方法来设置显示的图片和文字。最后返回布局 * */ Fruit fruit=getItem(position);//获取当前项的Fruit实例 //初始话ListView的子项布局 View view=LayoutInflater.from(getContext()).inflate(resourceId, null); ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image); TextView fruitName=(TextView) view.findViewById(R.id.fruit_name); fruitImage.setImageResource(fruit.getImageId()); fruitName.setText(fruit.getName()); return view; } }


    改动MainActivity的代码例如以下:

    package com.wj.listviewtest;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    public class MainActivity extends Activity {
    
    	/*private String [] data={"apple","banana","orange",
    			"watermelon","pear","grape","pineapple","strawberry",
    			"cherry","mango"};*/
    	private List<Fruit> fruitList=new ArrayList<Fruit>();
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		/*//创建适配器
    		ArrayAdapter<String> adapter=new ArrayAdapter<String>(
    				MainActivity.this,android.R.layout.simple_list_item_1,
    				data);
    		ListView listView=(ListView) findViewById(R.id.list_view);
    		listView.setAdapter(adapter);*/
    		initFruits();//初始化水果
    		FruitAdapter adapter=new FruitAdapter(MainActivity.this,
    				R.layout.fruit_item, fruitList);
    		ListView listView=(ListView) findViewById(R.id.list_view);
    		//设置适配器
    		listView.setAdapter(adapter);
    		
    	}
    
    	@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;
    	}
    	
    	public void initFruits(){
    		Fruit apple=new Fruit("apple",R.drawable.apple_pic);
    		fruitList.add(apple);
    		Fruit banana=new Fruit("banana",R.drawable.banana_pic);
    		fruitList.add(banana);
    		Fruit orange=new Fruit("orange",R.drawable.orange_pic);
    		fruitList.add(orange);
    		Fruit watermelon=new Fruit("watermelon",R.drawable.watermelon_pic);
    		fruitList.add(watermelon);
    		Fruit pear=new Fruit("pear",R.drawable.pear_pic);
    		fruitList.add(pear);
    		Fruit grape=new Fruit("grape",R.drawable.grape_pic);
    		fruitList.add(grape);
    		Fruit pineapple=new Fruit("pineapple",R.drawable.pineapple_pic);
    		fruitList.add(pineapple);
    		Fruit strawberry=new Fruit("strawberry",R.drawable.strawberry_pic);
    		fruitList.add(strawberry);
    		Fruit cherry=new Fruit("cherry",R.drawable.cherry_pic);
    		fruitList.add(cherry);
    		Fruit mango=new Fruit("mango",R.drawable.mango_pic);
    		fruitList.add(mango);
    	}
    	
    	
    
    }
    

    执行程序。结果例如以下:



    这是一个简单的界面。只是更加复杂的界面也能够通过改动fruit_item.xml文件来实现更加复杂的ListView。



    以下我们来提示下ListView的执行效率。

    眼下我们的ListView的执行效率是非常低的,由于在FruitAdapter的getView方法中每次都要将布局重写载入了一遍,当ListView高速滚动的时候这就会成为性能的瓶颈。细致观察。getView方法中另一个convertView參数。这个參数用于将之前载入好的布局进行缓存,以便之后能够进行重用,改动FruitAdapter中的代码。带入例如以下所看到的:

    @Override
    	public View getView(int position, View convertView, ViewGroup parent) {
    		// TODO Auto-generated method stub
    		//return super.getView(position, convertView, parent);
    		/*
    		 * 重写getView方法。这种方法在每一个子项被滚动到屏幕内的时候会被调用,在getView方法中
    		 * ,首先通过getItem方法得到当前项的Fruit实例。然后使用LayoutInflater来为这个子项载入
    		 * 我们传入的布局。接着调用View的findViewById方法分别获取到ImageView和TextView的实例。
    		 * 并分别调用他们的setImageResource和setText方法来设置显示的图片和文字。最后返回布局
    		 * */
    		Fruit fruit=getItem(position);//获取当前项的Fruit实例
    		View view;
    		/*
    		 * 在getView()方法中进行推断,假设convertView为空。则使用LayoutInflater去载入布局,
    		 * 假设不为空。则直接对convertView进行重用。这样能够大大提升ListView的效率,在高速滚动的时候
    		 * 也能够表现更好的性能。
    		 * */
    		if(convertView==null){
    			//初始话ListView的子项布局
    			view=LayoutInflater.from(getContext()).inflate(resourceId, null);
    		}else{
    			view=convertView;
    		}
    		/*//初始话ListView的子项布局
    		View view=LayoutInflater.from(getContext()).inflate(resourceId, null);*/
    		ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image);
    		TextView fruitName=(TextView) view.findViewById(R.id.fruit_name);
    		fruitImage.setImageResource(fruit.getImageId());
    		fruitName.setText(fruit.getName());
    		return view;
    	}

    上面的代码进行了部分的优化,尽管如今已经不用在反复的去载入布局了。可是每次在getView方法中还是会调用View的view.findViewById()方法来获取一次控件的实例。我们能够借助一个ViewHolder来对这部分性能进行优化,改动FruitAdapter中的代码。例如以下所看到的:

    package com.wj.listviewtest;
    
    import java.util.List;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    public class FruitAdapter extends ArrayAdapter<Fruit> {
    
    	private int resourceId;
    	public FruitAdapter(Context context, int textViewResourceId,
    			List<Fruit> objects) {
    		super(context, textViewResourceId, objects);
    		// TODO Auto-generated constructor stub
    		/*
    		 * 重写了父类的构造函数,用于将上下文,ListView子项布局的id和数据都传进来。
    		 * */
    		resourceId=textViewResourceId;
    	}
    	@Override
    	public View getView(int position, View convertView, ViewGroup parent) {
    		// TODO Auto-generated method stub
    		//return super.getView(position, convertView, parent);
    		/*
    		 * 重写getView方法,这种方法在每一个子项被滚动到屏幕内的时候会被调用,在getView方法中
    		 * 。首先通过getItem方法得到当前项的Fruit实例,然后使用LayoutInflater来为这个子项载入
    		 * 我们传入的布局,接着调用View的findViewById方法分别获取到ImageView和TextView的实例,
    		 * 并分别调用他们的setImageResource和setText方法来设置显示的图片和文字,最后返回布局
    		 * */
    		Fruit fruit=getItem(position);//获取当前项的Fruit实例
    		View view;
    		ViewHolder viewHolder;
    		/*
    		 * 在getView()方法中进行推断,假设convertView为空,则使用LayoutInflater去载入布局。
    		 * 假设不为空,则直接对convertView进行重用。这样能够大大提升ListView的效率。在高速滚动的时候
    		 * 也能够表现更好的性能。
    		 * */
    		if(convertView==null){
    			//初始话ListView的子项布局
    			view=LayoutInflater.from(getContext()).inflate(resourceId, null);
    		    viewHolder=new ViewHolder();
    		    viewHolder.fruitImage=(ImageView) view.findViewById(R.id.fruit_image);
    		    viewHolder.fruitName=(TextView) view.findViewById(R.id.fruit_name);
    		    view.setTag(viewHolder);//将ViewHolder存储在View中
    		}else{
    			view=convertView;
    			viewHolder=(ViewHolder) view.getTag();//又一次获取ViewHolder
    		}
    		/*//初始话ListView的子项布局
    		View view=LayoutInflater.from(getContext()).inflate(resourceId, null);*/
    		/*ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image);
    		TextView fruitName=(TextView) view.findViewById(R.id.fruit_name);*/
    		viewHolder.fruitImage.setImageResource(fruit.getImageId());
    		viewHolder.fruitName.setText(fruit.getName());
    		return view;
    	}
    	
    	
    	class ViewHolder{
    		ImageView fruitImage;
    		TextView  fruitName;
    	}
    
    }
    

    通过上面两步优化后,ListView的执行效率已经不错了。


    ListView的点击事件

    改动代码例如以下:

    package com.wj.listviewtest;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
    	/*private String [] data={"apple","banana","orange",
    			"watermelon","pear","grape","pineapple","strawberry",
    			"cherry","mango"};*/
    	private List<Fruit> fruitList=new ArrayList<Fruit>();
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		/*//创建适配器
    		ArrayAdapter<String> adapter=new ArrayAdapter<String>(
    				MainActivity.this,android.R.layout.simple_list_item_1,
    				data);
    		ListView listView=(ListView) findViewById(R.id.list_view);
    		listView.setAdapter(adapter);*/
    		initFruits();//初始化水果
    		FruitAdapter adapter=new FruitAdapter(MainActivity.this,
    				R.layout.fruit_item, fruitList);
    		ListView listView=(ListView) findViewById(R.id.list_view);
    		//设置适配器
    		listView.setAdapter(adapter);
    		/*
    		 * setOnItemClickListener()方法来为ListView注冊一个监听器。当用户点击了ListView
    		 * 中的不论什么一个子项时就会回调nItemClick()方法。在这种方法中能够通过position參数推断出用户点击
    		 * 的是哪一个子项,然后获取对应的水果。并通过Toast将水果的名字显示出来。
    		 * */
    		listView.setOnItemClickListener(new OnItemClickListener(){
    
    			@Override
    			public void onItemClick(AdapterView<?> parent, View view, int position,
    					long id) {
    				// TODO Auto-generated method stub
    				Fruit fruit=fruitList.get(position);
    				Toast.makeText(MainActivity.this, 
    						fruit.getName(), Toast.LENGTH_SHORT).show();
    				
    			}
    			
    		});
    	}
    
    	@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;
    	}
    	
    	public void initFruits(){
    		Fruit apple=new Fruit("apple",R.drawable.apple_pic);
    		fruitList.add(apple);
    		Fruit banana=new Fruit("banana",R.drawable.banana_pic);
    		fruitList.add(banana);
    		Fruit orange=new Fruit("orange",R.drawable.orange_pic);
    		fruitList.add(orange);
    		Fruit watermelon=new Fruit("watermelon",R.drawable.watermelon_pic);
    		fruitList.add(watermelon);
    		Fruit pear=new Fruit("pear",R.drawable.pear_pic);
    		fruitList.add(pear);
    		Fruit grape=new Fruit("grape",R.drawable.grape_pic);
    		fruitList.add(grape);
    		Fruit pineapple=new Fruit("pineapple",R.drawable.pineapple_pic);
    		fruitList.add(pineapple);
    		Fruit strawberry=new Fruit("strawberry",R.drawable.strawberry_pic);
    		fruitList.add(strawberry);
    		Fruit cherry=new Fruit("cherry",R.drawable.cherry_pic);
    		fruitList.add(cherry);
    		Fruit mango=new Fruit("mango",R.drawable.mango_pic);
    		fruitList.add(mango);
    	}
    	
    	
    
    }
    


    执行结果例如以下;



    好了ListView的使用就总结到这里了。

    单位和尺寸

    px是像素的意思,即屏幕中能够显示的最小单位,我们应用里不论什么可见的东西都是由一个个像素点组成的。

    pt是磅数的意思,1磅等于1/72英寸。一般pt都会作为字体的单位来使用。

    dp是密度无关的像素的意思,也被称作为dip,和px相比,它在不同密度的屏幕中的显示比例保持一致。

    sp是可伸缩像素的意思,它採用了和dp相同的设计理念,攻克了文字大小的适配问题。

    android中的密度就是屏幕每英寸所包括的像素数。通常以dpi为单位。

    依据android的规定,在160dpi的屏幕上,1dp等于1px,而在320dpi的屏幕上,1dp就等于2px。

    因此。使用dp来指定控件的宽和高。就能够保证控件在不同密度的屏幕中的显示比例保存一致。

    所以dp能够理解为显示比例(像素除以英寸)

    在编写android程序的时候,尽量将控件或布局的大小指定成match_parent或wrap_content,假设必需要指定一个固定的值,则使用dp来作为单位,指定文字的大小的时候使用sp。

    转载请注明来着:http://blog.csdn.net/j903829182/article/details/40683293


    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    Why Choose Jetty?
    Jetty 的工作原理以及与 Tomcat 的比较
    Tomcat设计模式
    Servlet 工作原理解析
    Tomcat 系统架构
    spring boot 打包方式 spring boot 整合mybaits REST services
    wireshark udp 序列号 User Datagram Protocol UDP
    Maven 的聚合(多模块)和 Parent 继承
    缓存策略 半自动化就是mybaitis只支持数据库查出的数据映射到pojo类上,而实体到数据库的映射需要自己编写sql语句实现,相较于hibernate这种完全自动化的框架我更喜欢mybatis
    Mybatis解决sql中like通配符模糊匹配 构造方法覆盖 mybits 增删改
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4749692.html
Copyright © 2011-2022 走看看