Adapter适配器基础讲解
MVC模式的简单理解
在开始学习Adapter之前我们要来了解下这个MVC模式概念:
举个例子:大型的商业程序通常由多人一同开发完成,比如有人
负责操作接口的规划与设计, 有人负责程序代码的编写如果要
能够做到程序项目的分工就必须在程序的结构上做适合的安排 ,
如果,接口设计与修改都涉及到程序代码的改变的话,那么两者
的分工就会造成执行上的困难 良好的程序架构师将整个程序
项目划分为如图的三个部分:

关系图解析:
* Model:通常可以理解为数据,负责执行程序的核心运算与判断逻辑,,通过view获得用户 输入的数据,然
后根据从数据库查询相关的信息,最后进行运算和判断,再将得到的结果交给view来显示
* view:用户的操作接口,说白了就是GUI,应该使用哪种接口组件,组件间的排列位置与顺序都需要设计
* Controller:控制器,作为model与view之间的枢纽,负责控制程序的执行流程以及对象之间的一个互动
M:model:数据模型——数据源,
V:view:显示的视图控件——AdapteView,
C:controller :控制器——adapter
AdapterView即Adapter(适配器)控件
AdapterView适配器View常用的有:ListView、GridView、Spinner、RecycleView
其内容通常是一个包含多项相同格式资源的列表,每次只显示其中一项。这个存放Adapter控件内容的列表,
在android被称为AdapterView(适配器View)使用的时候一般都会先给适配器填充内容。然后将已经设定
好内容的适配器(Adapter)设置到AdapterView上



Adapter概念解析
首先我们来看看他的继承结构图:

* BaseAdapter:抽象类,实际开发中我们会继承这个类并且重写相关方法,用得最多的一个Adapter!
* ArrayAdapter:支持泛型操作,最简单的一个Adapter,只能展现一行文字~
* SimpleAdapter:同样具有良好扩展性的一个Adapter,可以自定义多种效果!
* SimpleCursorAdapter:用于显示简单文本类型的listView,一般在数据库那里会用到,不过有点过时, 不推荐使用!
代码
AdapterActivity.java
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class AdapterActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.adapter_layout);
//AdapterView-- V
ListView listView = findViewById(R.id.listview);
//数据源-- M
String[] strs = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s"};
//控制器-- C
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(this, android.R.layout.simple_expandable_list_item_1, strs);
//为ListView设置Adapter适配器
listView.setAdapter(adapter);
}
}
adapter_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</ListView>
ListView
BaseAdapter最基本的几个方法:
1. getCount 填充的数据集数
2. getItem 数据集中指定索引对应的数据项
3. getItemId 指定行所对应的ID
4. getView 每个Item所显示的类容
public class News {
private String title;
private String content;
private int aIcon;
public News() {
}
public News(String title, String content, int aIcon) {
this.title = title;
this.content = content;
this.aIcon = aIcon;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getaIcon() {
return aIcon;
}
public void setaIcon(int aIcon) {
this.aIcon = aIcon;
}
}
public class NewsAdapter extends BaseAdapter {
private List<News> mData;
private Context mContext;
public NewsAdapter(List<News> mData, Context mContext) {
this.mData = mData;
this.mContext = mContext;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView =
LayoutInflater.from(mContext).inflate(R.layout.listview_item_layout,
parent, false);
ImageView img_icon = (ImageView)
convertView.findViewById(R.id.img_icon);
TextView title = (TextView)
convertView.findViewById(R.id.tv_title);
TextView content = (TextView)
convertView.findViewById(R.id.tv_content);
img_icon.setBackgroundResource(mData.get(position).getaIcon());
title.setText(mData.get(position).getTitle());
content.setText(mData.get(position).getContent());
return convertView;
}
}
public class ListViewActivity extends AppCompatActivity {
private List<News> mData = null;
private Context mContext;
private NewsAdapter mAdapter = null;
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_layout);
mContext = this;
listView = (ListView) findViewById(R.id.listview);
mData = new LinkedList<News>();
for (int i = 0; i < 10; i++) {
mData.add(new News("我是一个新闻标题---- " + i, "我是一个新闻内容----
" + i, R.mipmap.news));
}
mAdapter = new NewsAdapter(mData, mContext);
listView.setAdapter(mAdapter);
listView.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int
position, long id) {
Toast.makeText(mContext, "点击了第" + position + "条数据",
Toast.LENGTH_SHORT).show();
}
});
}
}
<?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="100dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="15dp">
<ImageView
android:id="@+id/img_icon"
android:layout_width="130dp"
android:layout_height="80dp"
android:src="@mipmap/news"/>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_weight="1">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="我是一个新闻标题---- 1"
android:textColor="#000000"
android:textSize="18dp" />
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="我是新闻内容---- 1"
android:textColor="#000000"
android:textSize="14dp" />
</RelativeLayout>
</LinearLayout>
BaseAdapter 优化
复用ConvertView
inflate()每次都要加载一次xml,其实这个convertView是系统提供给我们的可供复用的View
的缓存对象
if(convertView == null){
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list_animal,parent,false);
}
ViewHolder重用组件
static class ViewHolder{
ImageView img_icon;
TextView txt_aName;
TextView txt_aSpeak;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView =
LayoutInflater.from(mContext).inflate(R.layout.listview_item_layout
, parent
, false);
holder.img_icon = (ImageView)
convertView.findViewById(R.id.img_icon);
holder.title = (TextView)
convertView.findViewById(R.id.tv_title);
holder.content = (TextView)
convertView.findViewById(R.id.tv_content);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.img_icon.setBackgroundResource(mData.get(position).getaIcon());
holder.title.setText(mData.get(position).getTitle());
holder.content.setText(mData.get(position).getContent());
return convertView;
}
ListView item多布局实现
重写getItemViewType()方法对应View是哪个类别,以及getViewTypeCount()方法iew返回 总共多少个类别!然后再getView那里调用getItemViewType获得对应类别,再加载对应的View!
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.ttit.helloworld.R;
import com.ttit.helloworld.entity.News;
import java.util.List;
public class NewsAdapter2 extends BaseAdapter {
private List<News> mData;
private Context mContext;
//定义两个类别标志
private static final int TYPE_NEWS_1 = 0;
private static final int TYPE_NEWS_2 = 1;
public NewsAdapter2(List<News> mData, Context mContext) {
this.mData = mData;
this.mContext = mContext;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
//返回对应item布局类型
@Override
public int getItemViewType(int position) {
if (position % 2 == 0) {
return TYPE_NEWS_1;
} else {
return TYPE_NEWS_2;
}
}
//总共多少item布局类型
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
int type = getItemViewType(position); //获取布局类型
ViewHolder holder1 = null;
ViewHolder2 holder2 = null;
if (convertView == null) {
switch (type) {
case TYPE_NEWS_1:
holder1 = new ViewHolder();
convertView =
LayoutInflater.from(mContext).inflate(R.layout.listview_item_layout
, parent
, false);
holder1.img_icon = (ImageView)
convertView.findViewById(R.id.img_icon);
holder1.title = (TextView)
convertView.findViewById(R.id.tv_title);
holder1.content = (TextView)
convertView.findViewById(R.id.tv_content);
convertView.setTag(holder1);
break;
case TYPE_NEWS_2:
holder2 = new ViewHolder2();
convertView =
LayoutInflater.from(mContext).inflate(R.layout.listview_item_layout2
, parent
, false);
holder2.img_icon = (ImageView)
convertView.findViewById(R.id.img_icon);
holder2.title = (TextView)
convertView.findViewById(R.id.tv_title);
holder2.content = (TextView)
convertView.findViewById(R.id.tv_content);
convertView.setTag(holder2);
break;
}
} else {
switch (type) {
case TYPE_NEWS_1:
holder1 = (ViewHolder) convertView.getTag();
break;
case TYPE_NEWS_2:
holder2 = (ViewHolder2) convertView.getTag();
break;
}
}
switch (type) {
case TYPE_NEWS_1:
holder1.img_icon.setBackgroundResource(mData.get(position).getaIcon());
holder1.title.setText(mData.get(position).getTitle());
holder1.content.setText(mData.get(position).getContent());
break;
case TYPE_NEWS_2:
holder2.img_icon.setBackgroundResource(mData.get(position).getaIcon());
holder2.title.setText(mData.get(position).getTitle());
holder2.content.setText(mData.get(position).getContent());
break;
}
return convertView;
}
static class ViewHolder {
ImageView img_icon;
TextView title;
TextView content;
}
static class ViewHolder2 {
ImageView img_icon;
TextView title;
TextView content;
}
}

GridView网格视图
android:columnWidth:设置列的宽度
android:gravity:组件对其方式
android:horizontalSpacing:水平方向每个单元格的间距
android:verticalSpacing:垂直方向每个单元格的间距
android:numColumns:设置列数
android:stretchMode:设置拉伸模式,可选值如下:
none:不拉伸;
spacingWidth:拉伸元素间的间隔空隙
columnWidth:仅仅拉伸表格元素自身
spacingWidthUniform:既拉元素间距又拉伸他们之间的间隔空袭
GridViewActivity.java
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.ttit.helloworld.adapter.GridViewAdpater;
import com.ttit.helloworld.entity.Icon;
import java.util.ArrayList;
import java.util.List;
public class GridViewActivity extends AppCompatActivity {
private Context mContext;
private GridView grid_photo;
private GridViewAdpater mAdapter = null;
private List<Icon> mData = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gridview_layout);
mContext = this;
//视图层V
grid_photo = (GridView) findViewById(R.id.gridView);
//数据源M
mData = new ArrayList();
mData.add(new Icon(R.mipmap.iv_icon_1, "图标1"));
mData.add(new Icon(R.mipmap.iv_icon_2, "图标2"));
mData.add(new Icon(R.mipmap.iv_icon_3, "图标3"));
mData.add(new Icon(R.mipmap.iv_icon_4, "图标4"));
mData.add(new Icon(R.mipmap.iv_icon_5, "图标5"));
mData.add(new Icon(R.mipmap.iv_icon_6, "图标6"));
mData.add(new Icon(R.mipmap.iv_icon_7, "图标7"));
//控制层C
mAdapter = new GridViewAdpater(mData, mContext);
grid_photo.setAdapter(mAdapter);
//点击事件
grid_photo.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int
position, long id) {
Toast.makeText(mContext, "你点击了~" + position + "~项",
Toast.LENGTH_SHORT).show();
}
});
}
}
Spinner列表选项框
android:dropDownHorizontalOffset:设置列表框的水平偏移距离
android:dropDownVerticalOffset:设置列表框的水平竖直距离
android:dropDownSelector:列表框被选中时的背景
android:dropDownWidth:设置下拉列表框的宽度
android:gravity:设置里面组件的对其方式
android:popupBackground:设置列表框的背景
android:prompt:设置对话框模式的列表框的提示信息(标题),只能够引用string.xml 中的资源
id,而不能直接写字符串
android:spinnerMode:列表框的模式,有两个可选值: dialog:对话框风格的窗口 dropdown:
下拉菜单风格的窗口(默认)
可选属性:android:entries:使用数组资源设置下拉列表框的列表项目


ExpandableListView可折叠列表
实现ExpandableAdapter的三种方式
1. 扩展BaseExpandableListAdpter实现ExpandableAdapter。
2. 使用SimpleExpandableListAdpater将两个List集合包装成ExpandableAdapter
3. 使用simpleCursorTreeAdapter将Cursor中的数据包装成SimpleCuroTreeAdapter 本节示
例使用的是第一个,扩展BaseExpandableListAdpter,我们需要重写该类中的相关方法, 下面我们
通过一个代码示例来体验下!
*有一点要注意的是,重写isChildSelectable()方法需要返回true,不然不会触发子Item的点击事件*

Toast 吐司
Android用于提示信息的一个控件

AlertDialog对话框
Step 1:创建AlertDialog.Builder对象;
Step 2:调用setIcon()设置图标,setTitle()或setCustomTitle()设置标题;
Step 3:设置对话框的内容:setMessage()还有其他方法来指定显示的内容;
Step 4:调用setPositive/Negative/NeutralButton()设置:确定,取消,中立按钮;
Step 5:调用create()方法创建这个对象,再调用show()方法将对话框显示出来;
java设计模式:建造者模式-Builder模式
PopupWindow 悬浮框
与AlertDialog区别:
本质区别为:AlertDialog是非阻塞式对话框:AlertDialog弹出时,后台还可以做事情;而
PopupWindow是阻塞式对话框:PopupWindow弹出时,程序会等待,在PopupWindow退出前,程序一
直等待,只有当我们调用了dismiss方法的后,PopupWindow退出,程序才会向下执行。这两种区别的
表现是:AlertDialog弹出时,背景是黑色的,但是当我们点击背景,AlertDialog会消失,证明程序
不仅响应AlertDialog的操作,还响应其他操作,其他程序没有被阻塞,这说明了AlertDialog是非阻
塞式对话框;PopupWindow弹出时,背景没有什么变化,但是当我们点击背景的时候,程序没有响应,
只允许我们操作PopupWindow,其他操作被阻塞。
setContentView(View contentView):设置PopupWindow显示的View
getContentView():获得PopupWindow显示的View
showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
showAtLocation(View parent, int gravity, int x, int y): 相对于父控件的位置(例如
正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移 PS:parent这个参数
只要是activity中的view就可以了!
setWidth/setHeight:设置宽高,也可以在构造方法那里指定好宽高, 除了可以写具体的值,还可
以用WRAP_CONTENT或MATCH_PARENT, popupWindow的width和height属性直接和第一层View相
对应。
setFocusable(true):设置焦点,PopupWindow弹出后,所有的触屏和物理按键都由
PopupWindows 处理。其他任何事件的响应都必须发生在PopupWindow消失之后,(home 等系统层
面的事件除外)。 比如这样一个PopupWindow出现的时候,按back键首先是让PopupWindow消失,第
二次按才是退出 activity,准确的说是想退出activity你得首先让PopupWindow消失,因为不并是
任何情况下按back PopupWindow都会消失,必须在PopupWindow设置了背景的情况下 。
setAnimationStyle(int):设置动画效果
Android UI之Adapter适配器基础讲解
251

被折叠的 条评论
为什么被折叠?



