您的位置:首页 > 移动开发 > Android开发

Android ListView嵌套GridView方法

2015-09-10 14:53 489 查看
目录

一、简介

二、使用详细步骤

三、总结

正文

一、简介

在做android应用开发中,ListView组件使用是相当频繁,几乎每个应用都会用到ListView组件。那么如果Listview的Item简单布局,毫无疑问这是每个android应用开发人员都会的。但是,我们在做应用有些Item布局就不是那么简单。例如,Listview的Item里面嵌套有Listview或者GridView等复杂布局,我们该怎么来实现这个需求呢?下面这篇文章主要讲解ListView嵌套怎样嵌套GridView。

二、使用详细步骤

第一、新建Activity类:QianTaoListViewActivity,比较简单,我直接上代码:

package bluesky.example.com.mvpdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;

import com.bluesky.easyandroid.base.CustomAdapter;
import com.bluesky.easyandroid.base.ViewHolder;

import java.util.ArrayList;
import java.util.List;

public class QianTaoListViewActivity extends Activity {
private ArrayList<String> datas;
private ArrayList<String> gridDatas;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qian_tao_list_view);
initData();
initView();
}

private void initData() {
datas = new ArrayList<String>();
for (int i = 0; i < 3; i++) {
datas.add("数据" + i);
}
gridDatas=new ArrayList<String>();
for (int i = 0; i < 10; i++) {
gridDatas.add("Grid数据" + i);
}
}

private void initView() {
ListView mListView = (ListView) findViewById(R.id.my_listView);
MyAdapter adapter = new MyAdapter(datas, R.layout.activity_qian_tao_list_item_view);
mListView.setAdapter(adapter);
}

private class MyAdapter extends CustomAdapter<String> {

/**
* 实例化该对象时,通过此构造函数传递相应的值
*
* @param list     数据源 List类型的值
* @param layoutId
*/
public MyAdapter(List<String> list, int layoutId) {
super(list, layoutId);
}

@Override
public void convert(ViewHolder holder, String bean) {
holder.setText(R.id.listview_item_tv, bean);
NoScrollGridView gridView = (NoScrollGridView) holder.getView(R.id.listview_item_gridview);
gridView.setAdapter(new MyGridAdapter(gridDatas, R.layout.gridview_item));
}
}

private class MyGridAdapter extends CustomAdapter<String> {

/**
* 实例化该对象时,通过此构造函数传递相应的值
*
* @param mList    数据源 List类型的值
* @param layoutId
*/
public MyGridAdapter(List<String> mList, int layoutId) {
super(mList, layoutId);
}

/**
* 提供给实现类实现的方法
*
* @param holder ViewHolder对象
* @param bean
*/
@Override
public void convert(ViewHolder holder, String bean) {
String url = "https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/fresco-logo.png";
holder.setImageURI(R.id.my_image_draweeview,url);
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_qian_tao_list_view, 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();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}
}


二、QianTaoListViewActivity对应的Xml文件,就是一个ListView组件:

<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"
>

<ListView
android:id="@+id/my_listView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:focusable="false"
/>

</RelativeLayout>


三、ListView组件对应的Item的Xml文件:

<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:orientation="vertical"
>
<TextView
android:id="@+id/listview_item_tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="数据标题"
/>
<bluesky.example.com.mvpdemo.NoScrollGridView
android:id="@+id/listview_item_gridview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchMode="columnWidth"
android:verticalSpacing="5dip"
android:horizontalSpacing="5dip"
android:numColumns="5"/>

</LinearLayout>


四、Gridview对应的Item的Xml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>

<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_draweeview"
android:layout_width="60dp"
android:layout_height="60dp"
fresco:placeholderImage="@mipmap/ic_launcher"/>
</LinearLayout>


五、号称万能适配器,网上很流行:

package com.bluesky.easyandroid.base;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import java.util.List;

/**
* @author 作者:pengyu
* @version 版本号:1.0
* @date 创建时间:2015年5月4日 上午11:15:29
* @description 类描述:自定义Adapter基类,灵活性最强
*/
public abstract class CustomAdapter<T> extends BaseAdapter {
/**
* 用于获取通过构造函数传递过来的数据源
*/
protected List<T> mList;
/**
* 用于接收通过构造函数传递过来的布局id
*/
protected int layoutId;

public CustomAdapter() {
super();
}

/**
* 实例化该对象时,通过此构造函数传递相应的值
*
* @param list
*            数据源 List类型的值
* @param layoutId
*            item使用的布局id
*/
public CustomAdapter(List<T> list, int layoutId) {
this.mList = list;
this.layoutId = layoutId;
}

/**
* 设置ListView中的数据,通知适配器改变
*
* @param mList
*/
public void notifyDataChanged(List<T> mList) {
this.mList = mList;
notifyDataSetChanged();
}

/**
* 获取数据源的总数量-->item的个数-->数据源的长度 必须得到真实的数据源项数,否则不能适配数据,
*
* @return 返回填充的数据项的个数
*/
public int getCount() {
if (mList != null) {
return mList.size();
}
return 0;
}

/**
* 获取与指定的位置相关联的数据项的数据集。
*
* @position:数据项的索引,从0开始
* @return:根据position返回某一项数据
*/
public T getItem(int position) {
if (mList != null) {
return mList.get(position);
}
return null;
}

/**
* 提供给外部获取相应位置上面的数据
*
* @position:数据项的索引,从0开始
* @return:根据position返回某一项的行ID
*/
public long getItemId(int position) {
if (mList != null) {
return position;
}
return 0;
}

/**
* @position:数据项索引,从0开始
* @convertView:需要重用的View,每一次都要检查它是否null,若不是,则直接重用它,若是,则需要新建一个View
* @parent 得到的View的父View(即ListView)
* @return 返回需要填充的数据,一次只填充一项,根据position决定是哪一项(填充一个item就会调用一次getView()方法)
*         对于ListView中的
*         数据,显示每一行都需要调用一次该方法,用convertview和viewHolder一同完成缓存机制,以优化性能
*/
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = ViewHolder.get(position, convertView, parent,
layoutId);
convert(holder, getItem(position));
return holder.getConvertView();
}

/**
* 提供给实现类实现的方法
*
* @param holder
*            ViewHolder对象
* @param bean
*            实体对象
*/
public abstract void convert(ViewHolder holder, T bean);

}


ViewHolder

package com.bluesky.easyandroid.base;

import android.graphics.Bitmap;
import android.net.Uri;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.facebook.drawee.view.SimpleDraweeView;

/**
* @author 作者:pengyu
* @version 版本号:1.0
* @date 创建时间:2015年5月4日 上午11:15:29
* @description 类描述:自定义Adapter使用的ViewHolder
*/
public class ViewHolder {
/**
* SparseArray类似于map,<int key,value object> 效率比hashMap高
*/
private SparseArray<View> mViews;
private int mPosition;
private View mConvertView;

/**
* @param parent
* @param layoutId
* @param position
*/
public ViewHolder(int position, ViewGroup parent, int layoutId) {
this.mPosition = position;
this.mViews = new SparseArray<View>();
this.mConvertView = LayoutInflater.from(parent.getContext()).inflate(layoutId, null);
mConvertView.setTag(this);
}

public static ViewHolder get(int position, View convertView, ViewGroup parent, int layoutId) {
//当convertView为空时,才需要创建ViewHolder的实例
if (convertView == null) {
return new ViewHolder(position, parent, layoutId);
} else {
ViewHolder holder = (ViewHolder) convertView.getTag();
holder.mPosition = position;//更新position的位置
return holder;
}
}

/**
* 通过viewId获取控件
*
* @param viewId
*
* @return 指定id的控件
*/
public <T extends View> T getView(int viewId) {
//获取指定id的控件
View view = mViews.get(viewId);
//判断是否存储过,没有的话通过mConvertView绑定控件,并存储到mViews中
if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}

/**
* 用于返回ConvertView
*
* @return mConvertView
*/
public View getConvertView() {
return mConvertView;
}

/**
* 用于返回当前点击的item的位置
*
* @return Position
*/
public int getPosition() {
return mPosition;
}

/**
* 设置TextView的值
*
* @param viewId
* @param text
*
* @return
*/
public ViewHolder setText(int viewId, String text) {
TextView tView = getView(viewId);
tView.setText(text);
return this;
}

/**
* 设置ImageView的值(通过图片资源)
*
* @param viewId
*
* @return
*/
public ViewHolder setImageResource(int viewId, int resId) {
ImageView imgView = getView(viewId);
imgView.setImageResource(resId);
return this;
}

/**
* 设置ImageView的值(通过bitmap)
*
* @param viewId
* @param bm
*
* @return
*/
public ViewHolder setImageResource(int viewId, Bitmap bm) {
ImageView imgView = getView(viewId);
imgView.setImageBitmap(bm);
return this;
}

/**
* 设置ImageView的值(网络图片)
*
* @param viewId
* @param url
*
* @return
*/
public ViewHolder setImageURI(int viewId, String url) {
SimpleDraweeView imgView = getView(viewId);
imgView.setImageURI(Uri.parse(url));
return this;
}

}


三、总结

界面这些比较简单,目的主要是实现功能。所有逻辑代码都在QianTaoListViewActivity里面。包括两个适配器,一个是ListView的适配器,另一个是GridView适配器。这两个适配器都继承CustomAdapter,这个是现在比较流行的Adapter封装,目的减少很多重复性代码。这里需要注意适配的问题,因为我的GridView里面是图片,里面图片宽度尺寸不能不能超过GridView的Item尺寸,否则图片会变形。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: