android listview多种布局,使得ListView能够呈现多种布局的多布局适配器



/*

* Copyright (C) 2006 The Android Open Source Project

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

*      http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

packageandroid.widget;

importjava.util.ArrayList;

importjava.util.List;

importjava.util.Map;

importandroid.content.Context;

importandroid.net.Uri;

importandroid.view.LayoutInflater;

importandroid.view.View;

importandroid.view.ViewGroup;

importandroid.widget.BaseAdapter;

importandroid.widget.Checkable;

importandroid.widget.Filter;

importandroid.widget.Filterable;

importandroid.widget.ImageView;

importandroid.widget.Spinner;

importandroid.widget.TextView;

/**

* 这是一个简单的适配器,可以将静态数据映射到XML文件中定义好的视图.

* 你可以将 Maps 的 ArrayList 指定为用于列表的数据.ArrayList 中的每一项对应列表中的一行.

* Maps 中包含用于一行的数据.你也可以指定 XML 文件,其中定义了用于显示行的视图,通过

* Map 的关键字映射到指定的视图.

* 绑定数据到视图分两个阶段.首先,如果 {@link android.widget.SimpleAdapter.ViewBinder} 是有效的,

* 则调用 {@link ViewBinder#setViewValue(android.view.View, Object, String)} 方法.

* 如果返回值为真,则执行绑定.如果返回值为假,则按以下顺序绑定视图:

* *

实现了 Checkable 的视图(例如 CheckBox),期望绑定值是布尔类型.

*

TextView,期望绑定值是字符串类型,通过调用 {@link #setViewText(TextView, String)} 绑定.

*

ImageView,期望绑定值是资源 ID 或者一个字符串,通过调用

* {@link #setViewImage(ImageView, int)} 或 {@link #setViewImage(ImageView, String)}绑定.

*

* 如果没有合适的绑定发生,将会抛出 {@link IllegalStateException} 异常.

* @author translate by 德罗德

* @author convert by cnmahj

*/

publicclassMultiLayoutSimpleAdapterextendsBaseAdapterimplementsFilterable {

privateint[] mTo;

privateString[] mFrom;

privateViewBinder mViewBinder;

protectedListextendsMap

privateint[] mResources;

privateint[] mDropDownResources;

privateLayoutInflater mInflater;

privateSimpleFilter mFilter;

privateArrayList

/**

* 构造函数

*

* @param context 与 SimpleAdapter 关联的运行着的视图的上下文.

* @param data Map 的列表.列表中的每个条目对应一行.Maps 中包含所有在 from 中指定的数据.

* @param resource 定义列表项目的视图布局的资源 ID.布局文件至少应该包含在 to 中定义了的名称.

* @param from 与 Map 中的项目建立关联的列名的列表.

* @param to 用于显示 from 中参数中的列的视图列表.这些视图应该都是 TextView 类型的.

* 该列表中的第 N 个视图显示从参数 from 中的第 N 列获取的值.

*/

publicMultiLayoutSimpleAdapter(Context context, ListextendsMap

int[] resources, String[] from,int[] to) {

mData = data;

mResources = mDropDownResources = resources;

mFrom = from;

mTo = to;

mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

}

@Override

publicintgetViewTypeCount() {

returnmResources.length;

}

/**

* @see android.widget.Adapter#getCount()

*/

publicintgetCount() {

returnmData.size();

}

/**

* @see android.widget.Adapter#getItem(int)

*/

publicObject getItem(intposition) {

returnmData.get(position);

}

/**

* @see android.widget.Adapter#getItemId(int)

*/

publiclonggetItemId(intposition) {

returnposition;

}

/**

* @see android.widget.Adapter#getView(int, View, ViewGroup)

*/

publicView getView(intposition, View convertView, ViewGroup parent) {

returncreateViewFromResource(position, convertView, parent, mResources[getItemViewType(position)]);

}

privateView createViewFromResource(intposition, View convertView,

ViewGroup parent, intresource) {

View v;

if(convertView ==null) {

v = mInflater.inflate(resource, parent, false);

} else{

v = convertView;

}

bindView(position, v);

returnv;

}

/**

*

设置创建下拉列表视图的布局资源 ID.

*

* @param resource 定义下拉列表视图的布局资源 ID.

* @see #getDropDownView(int, android.view.View, android.view.ViewGroup)

*/

publicvoidsetDropDownViewResource(int[] resources) {

this.mDropDownResources = resources;

}

@Override

publicView getDropDownView(intposition, View convertView, ViewGroup parent) {

returncreateViewFromResource(position, convertView, parent, mResources[getItemViewType(position)]);

}

privatevoidbindView(intposition, View view) {

finalMap

if(dataSet ==null) {

return;

}

finalViewBinder binder = mViewBinder;

finalString[] from = mFrom;

finalint[] to = mTo;

finalintcount = to.length;

for(inti =0; i 

finalView v = view.findViewById(to[i]);

if(v !=null) {

finalObject data = dataSet.get(from[i]);

String text = data == null?"": data.toString();

if(text ==null) {

text = "";

}

booleanbound =false;

if(binder !=null) {

bound = binder.setViewValue(v, data, text);

}

if(!bound) {

if(vinstanceofCheckable) {

if(datainstanceofBoolean) {

((Checkable) v).setChecked((Boolean) data);

} elseif(vinstanceofTextView) {

// Note: keep the instanceof TextView check at the bottom of these

// ifs since a lot of views are TextViews (e.g. CheckBoxes).

setViewText((TextView) v, text);

} else{

thrownewIllegalStateException(v.getClass().getName() +

" should be bound to a Boolean, not a "+

(data == null?": data.getClass()));

}

} elseif(vinstanceofTextView) {

// Note: keep the instanceof TextView check at the bottom of these

// ifs since a lot of views are TextViews (e.g. CheckBoxes).

setViewText((TextView) v, text);

} elseif(vinstanceofImageView) {

if(datainstanceofInteger) {

setViewImage((ImageView) v, (Integer) data);

} else{

setViewImage((ImageView) v, text);

}

} elseif(vinstanceofSpinner) {

if(datainstanceofInteger) {

((Spinner)v).setSelection((Integer) data);

} else{

continue;

}

} else{

thrownewIllegalStateException(v.getClass().getName() +" is not a "+

" view that can be bounds by this SimpleAdapter");

}

}

}

}

}

/**

* 返回用于将数据绑定到视图的 {@link ViewBinder}.

*

* @return ViewBinder,如果绑定器不存在则返回 null.

*

* @see #setViewBinder(android.widget.SimpleAdapter.ViewBinder)

*/

publicViewBinder getViewBinder() {

returnmViewBinder;

}

/**

* 设置用于将数据绑定到视图的绑定器.

*

* @param viewBinder 用于将数据绑定到视图的绑定器.设置为 null,可以删除既存的绑定器.

*

* @see #getViewBinder()

*/

publicvoidsetViewBinder(ViewBinder viewBinder) {

mViewBinder = viewBinder;

}

/**

* 由 bindView() 方法调用,用于为 ImageView 设置图像.只在

* ViewBinder 不存在或者既存的 ViewBinder 无法处理 ImageView 的绑定时才调用.

*

* 如果调用 {@link #setViewImage(ImageView, String)} 方法时提供的

* value 参数可以转换为整数类型,则会自动调用本方法.

*

* @param v 接收图像的 ImageView.

* @param value 从数据集获取到的值

*

* @see #setViewImage(ImageView, String)

*/

publicvoidsetViewImage(ImageView v,intvalue) {

v.setImageResource(value);

}

/**

* 由 bindView() 方法调用,用于为 ImageView 设置图像.只在

* ViewBinder 不存在或者既存的 ViewBinder 无法处理 ImageView 的绑定时才调用.

*

* 本方法默认将 value 作为图像资源 ID 来对待;当 value

* 无法变换为整数类型时,才作为图像的 Uri 来使用.

*

* @param v 接收图像的 ImageView.

* @param value 从数据集获取到的值.

*

* @see #setViewImage(ImageView, int)

*/

publicvoidsetViewImage(ImageView v, String value) {

try{

v.setImageResource(Integer.parseInt(value));

} catch(NumberFormatException nfe) {

v.setImageURI(Uri.parse(value));

}

}

/**

* 由 bindView() 方法调用,用于为 TextView 设置文本.只在

* ViewBinder 不存在或者既存的 ViewBinder 无法处理 TextView 的绑定时才调用.

*

* @param v 接收文本的 TextView.

* @param text 设置到 TextView 的文本.

*/

publicvoidsetViewText(TextView v, String text) {

v.setText(text);

}

publicFilter getFilter() {

if(mFilter ==null) {

mFilter = newSimpleFilter();

}

returnmFilter;

}

/**

* 该类用于 SimpleAdapter 的外部客户将适配器的值绑定到视图.

*

* 你可以使用此类将 SimpleAdapter 不支持的值绑定到视图,或者改变 SimpleAdapter

* 支持的视图的绑定方式.

*

* @see MultiLayoutSimpleAdapter#setViewImage(ImageView, int)

* @see MultiLayoutSimpleAdapter#setViewImage(ImageView, String)

* @see MultiLayoutSimpleAdapter#setViewText(TextView, String)

*/

publicstaticinterfaceViewBinder {

/**

* 绑定指定的数据到指定的视图.

*

* 当使用 ViewBinder 绑定了数据时,必须返回真.如果该方法返回假,

* SimpleAdapter 会用自己的方式去绑定数据.

*

* @param view 要绑定数据的视图

* @param data 绑定用的数据

* @param textRepresentation 代表所提供的数据的安全字符串:

*        或者是 data.toString(),或者是空串,不能为空.

*

* @return 如果将数据绑定到了视图,返回真;否则返回假.

*/

booleansetViewValue(View view, Object data, String textRepresentation);

}

/**

*

An array filters constrains the content of the array adapter with

* a prefix. Each item that does not start with the supplied prefix

* is removed from the list.

*/

privateclassSimpleFilterextendsFilter {

@Override

protectedFilterResults performFiltering(CharSequence prefix) {

FilterResults results = newFilterResults();

if(mUnfilteredData ==null) {

mUnfilteredData = newArrayList

}

if(prefix ==null|| prefix.length() ==0) {

ArrayList

results.values = list;

results.count = list.size();

} else{

String prefixString = prefix.toString().toLowerCase();

ArrayList

intcount = unfilteredValues.size();

ArrayList

for(inti =0; i 

Map

if(h !=null) {

intlen = mTo.length;

for(intj=0; j

String str =  (String)h.get(mFrom[j]);

String[] words = str.split(" ");

intwordCount = words.length;

for(intk =0; k 

String word = words[k];

if(word.toLowerCase().startsWith(prefixString)) {

newValues.add(h);

break;

}

}

}

}

}

results.values = newValues;

results.count = newValues.size();

}

returnresults;

}

@Override

protectedvoidpublishResults(CharSequence constraint, FilterResults results) {

//noinspection unchecked

mData = (List

if(results.count >0) {

notifyDataSetChanged();

} else{

notifyDataSetInvalidated();

}

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当使用ListView时,可以定义一个布局文件作为每个列表项的外观。以下是一个简单的例子: 首先,创建一个名为 `list_item.xml` 的新布局文件,它将包含一个ImageView和两个TextView。布局如下: ```xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp"> <ImageView android:id="@+id/item_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher"/> <LinearLayout android:orientation="vertical" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:layout_marginStart="10dp"> <TextView android:id="@+id/item_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Item Title"/> <TextView android:id="@+id/item_description" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Item Description"/> </LinearLayout> </LinearLayout> ``` 在这个布局文件中,我们定义了一个水平方向的LinearLayout,它包含一个ImageView和一个竖直方向的LinearLayout。竖直方向的LinearLayout包含两个TextView,分别用于显示标题和描述。我们还将LinearLayout的权重设置为1,这将使标题和描述填满空白区域。 接下来,将该布局文件用作ListView的每个列表项的布局。在ListView适配器中,可以通过以下方式使用该布局文件: ```java public class MyAdapter extends BaseAdapter { private List<Item> mItems; private Context mContext; public MyAdapter(Context context, List<Item> items) { mContext = context; mItems = items; } @Override public int getCount() { return mItems.size(); } @Override public Object getItem(int position) { return mItems.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if (view == null) { LayoutInflater inflater = LayoutInflater.from(mContext); view = inflater.inflate(R.layout.list_item, parent, false); } Item item = mItems.get(position); ImageView icon = (ImageView) view.findViewById(R.id.item_icon); icon.setImageResource(item.getIcon()); TextView title = (TextView) view.findViewById(R.id.item_title); title.setText(item.getTitle()); TextView description = (TextView) view.findViewById(R.id.item_description); description.setText(item.getDescription()); return view; } } ``` 在适配器的getView()方法中,我们获取要在该位置显示的Item对象,然后使用该对象的数据填充视图中的ImageView和TextView。如果convertView为空,则使用LayoutInflater将列表项的布局文件转换为View对象。最后,返回填充数据的视图。 ### 回答2: 当然,我可以给您提供一个Android ListView布局例子。 首先,在您的布局文件中,您需要添加一个ListView组件。例如,您可以在XML文件中添加以下代码: ```xml <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent"/> ``` 接下来,在您的Activity或Fragment中,您需要引用这个ListView,并为其设置适配器,以便显示数据。以下是一个简单的例子: ```java ListView listView = findViewById(R.id.listview); ArrayList<String> dataList = new ArrayList<>(); // 假设您有一个String数组作为数据源 String[] data = {"Apple", "Banana", "Cherry", "Durian", "Elderberry"}; // 将数据源添加到ArrayList中 Collections.addAll(dataList, data); // 创建适配器,并将数据源传递给它 ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, dataList); // 将适配器设置给ListView listView.setAdapter(adapter); ``` 以上例子中,我们使用了Android提供的简单列表项布局(android.R.layout.simple_list_item_1)作为ListView的每个项的布局。 最后,在您的Activity或Fragment中,您可以为ListView设置一个点击事件监听器,以响应用户对列表项的点击。例如,您可以使用以下代码: ```java listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 在这里处理用户点击列表项的逻辑 Toast.makeText(MainActivity.this, "You clicked " + dataList.get(position), Toast.LENGTH_SHORT).show(); } }); ``` 这个例子展示了如何创建一个简单的Android ListView布局,并为其设置适配器和点击事件监听器。您可以根据自己的需求,对ListView进行更多的自定义和修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值