ListView 的简单实现与优化并实现share动画Activity的跳转
这篇文章主要是实现ListView的简单运用,即自定义ListView,在android 5.0之前ListView是应用最广泛的一个系统组件,
由于5.0后新的RecyclerView改良了ListView,所以5.0以后都开始应用RecyclerView,但是作为一个追求完美的程序猿,你必须具备这些技能,下面就让我们来看看ListView是实现,先来果
这就是整体效果图,下面我们来一一实现
先来看看ListView 中的布局
在activity_mian.xml布局中加一个ListView非常简单
<ListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/lv_item" />但是如果只加这个控件的话是不能显示的 还必须定义一个Adapter适配器,就是用来适配数据显示在布局中的
这里我们用到的自定义布局list_item.xml用来显示ListView中每个Item的内容
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:layout_width="40dp" android:layout_height="40dp" android:id="@+id/iv_img" android:src="@drawable/a" android:transitionName="iv_ico"/> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:text="11111111" android:layout_alignParentTop="true" android:layout_toEndOf="@+id/iv_img" android:id="@+id/tv_name" android:transitionName="tv_name"/> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:text="1111111111" android:layout_below="@+id/tv_name" android:layout_toEndOf="@+id/iv_img" android:id="@+id/tv_intro" android:transitionName="tv_intro"/> </RelativeLayout>
然后自定义一个Person类 ListView的每Item就用于显示Person的字段(属性)
public class Person implements Serializable{ private int icoId; private String name; private String intro; public Person(int icoId,String name,String intro){ this.icoId=icoId; this.name=name; this.intro=intro; }这里为了篇幅get,set方法就自己用快捷方式生成吧
然后在写个自定义的Adapter用来适配listView数据
public class MyAdapter extends ArrayAdapter { private int resourceId; public MyAdapter(Context context, int textViewResourceId, List<Person> objects){ super(context,textViewResourceId,objects); resourceId=textViewResourceId; } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { Person person = (Person) getItem(position); View view; ViewHolder viewHolder; if(convertView == null){ view = LayoutInflater.from(getContext()).inflate(R.layout.list_item,parent,false); viewHolder = new ViewHolder(); viewHolder.personImage=(ImageView)view.findViewById(R.id.iv_img); viewHolder.personName=(TextView)view.findViewById(R.id.tv_name); viewHolder.personIntro=(TextView)view.findViewById(R.id.tv_intro); view.setTag(viewHolder);//将viewHolder储存在view中 }else{ view=convertView; viewHolder=(ViewHolder)view.getTag();//重新获取viewHolder } viewHolder.personImage.setImageResource(person.getIcoId()); viewHolder.personName.setText(person.getName()); viewHolder.personIntro.setText(person.getIntro()); return view; } class ViewHolder{ ImageView personImage; TextView personName; TextView personIntro; } }这里自定义的MyAdapter继承的ArrayAdapter,先看看android中的适配器的继承树
这里我们继承的ArrayAdapter,这个适配器我觉得很好用 一般情况也够用这里我们重写了它的getView方法,该方法就是
用来加载listview中每个item中的内容的由于ListView还有性能优化的问题,所以这里把ListView的优化问题一并写了
getView方法中的ViewconvertView参数就是将之前加载的布局缓存起来以便重用,所以我们解析布局之前做个判断
如果converView为null则解析加载布局,如果已经加载过了就直接用converView,然后因为在加载布局是要通过findViewById来加载每个控件的实例 ,所以写个内部类来优化这样一来加载每个Item就只用加载一次布局,也只会存在每个控件的一个实例,现在的ListView在快速滑动是的效率就大大提高了.写好了自定义的adapter然后就是为ListView设置适配器了在MainActivity中设置
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initPerson(); MyAdapter adapter = new MyAdapter(MainActivity.this, R.layout.list_item,persons); ListView list = (ListView)findViewById(R.id.lv_item); list.setAdapter(adapter);这里由于是测试所以就写个initPerson()方法手动为ListView初始化数据了
private void initPerson() { for(int i=0;i<3;i++){ Person person1 = new Person(R.drawable.a,"android","android开发者"); persons.add(person1); Person person2 = new Person(R.drawable.b,"WEB","WEB开发者"); persons.add(person2); Person person3 = new Person(R.drawable.c,"嵌入式","android开发者"); persons.add(person3); Person person4 = new Person(R.drawable.d,"JAVA","android开发者"); persons.add(person4); Person person5 = new Person(R.drawable.e,"C#","C#开发者"); persons.add(person5); Person person6 = new Person(R.drawable.f,"前端","前端开发者"); persons.add(person6); Person person7 = new Person(R.drawable.g,"IOS","IOS开发者"); persons.add(person7); } }这样就是实现了自定义ListView的显示,但是ListView光显示是不够的,还要能有点击事件了
listView有自己的OnItemClickListener接口,实现点击事件很简单
list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(MainActivity.this, BActivity.class); Person person = persons.get(position); int icoId=person.getIcoId(); Bundle bundle = new Bundle(); bundle.putSerializable("person",person); intent.putExtras(bundle); View ico = findViewById(R.id.iv_img); View name =findViewById(R.id.tv_name); View intro=findViewById(R.id.tv_intro); startActivity(intent, ActivityOptions.makeSceneTransitionAnimation((Activity) view.getContext(), Pair.create(ico,"iv_ico"), Pair.create(name,"tv_name"), Pair.create(intro,"tv_intro")).toBundle()); } });这里面的代码是实现share动画跳转Activity的代码,可能有的人看不懂,没关系,里面的代码可以忽略
直接用Toast测试
list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this,"on click"+position+"",Toast.LENGTH_SHORT).show(); });如果想看share动画的可以看看上一篇文章
下一篇就写自定义的RecyclerView 由于RecyclerView的实现比ListView要复杂的多所以有必要做对比