前言
AdapterView与Adapter
控制层: Adapter适配器承担了控制层的角色
视图层: AdapterView将前端显示和后端数据分离
模型层: 数组、XML文件、List(ArrayList,LinkList)等形式的数据
AdapterView组件
AdapterView特征
AdapterView继承了ViewGroup,其本质上是容器
AdapterView可以包括多个“列表项”,并将“列表项”以合适的形式显示出来
AdapterView所显示的“列表项”是由Adapter提供,通过AdapterView的setAdapter()方法来设置Adapter适配器
AdapterView及其子类的继承关系
ps:通常将ListView、GridView、Spinner和Gallery等AdapterView子类作为容器,然后使用Adapter为容器提供“列表项”,AdapterView负责采用合适的方式显示这些列表项。
Adapter的常用子接口
ListAdapter接口
SimpleAdapter类
SimpleCursorAdapter类
ArrayAdapter类
BaseAdapter抽象类
ListView ListView列表视图
ListView通常具有两个职责:
将数据填充到布局,以列表的方式来显示数据
处理用户的选择、点击等操作Adapter类
通常创建ListView有以下两种方式:
直接使用ListView进行创建
使用Activity继承ListActivity,实现ListView对象的获取
ListView的独有属性
XML属性
功能描述
android:divider
设置列表的分隔条
android:dividerHeight
用来指定分隔条的高度
android:entries
指定一个数组资源
android:footerDividersEnabled
各个footer之间绘制分隔条
android:headerDividersEnabled
各个header之间绘制分隔条
ListView从AbsListView中继承的属性
XML属性
功能描述
android:cacheColorHint
用于设置该列表的背景始终以单一、固定的颜色绘制
android:choiceMode
为视图指定选择的行为
android:drawSelectorOnTop
如果为true,选中的列表项将会显示在上面
android:fastScrollEnabled
用于设置是否允许使用快速滚动滑块
android:listSelector
设置选中项显示的可绘制对象
android:scrollingCache
设置在滚动时是否使用绘制缓存,默认为true。
android:smoothScrollbar
列表会使用更精确的基于条目在屏幕上的可见像素高度的计算方法
android:stackFromBottom
设置是否将列表项从底部开始显示
android:textFilterEnabled
设置是否对列表项进行过滤
android:transcriptMode
设置该组件的滚动模式
使用ListView步骤
准备ListView所要显示的数据
使用数组或List集合存储数据
创建适配器(Adapter),作为列表项数据源
将适配器对象(Adapter)添加到ListView,并进行展示
自定义的ListView
ListView组件id为用户自定义字段
复杂ListView的使用
实现图文混排步骤:
定义行选项的布局格式
自定义一个Adapter,并重写其中的关键方法
注册列表选项的单击事件
创建Activity并加载对应的布局文件
ArrayAdapter 用ArrayAdapter实现ListView步骤
步骤其实和使用ListView是一样的,这里简写成三步
准备ListView所要显示的数据
将数据和适配器(Adapter)相关联
将适配器对象(Adapter)添加到ListView,并进行展示
测试样例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 package com.gallifrey.todayapplication.listview;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.Toast;import com.gallifrey.todayapplication.R;import java.util.LinkedList;import java.util.List;public class ListViewActivity extends AppCompatActivity { private ListView mlv; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_list_view); mlv=findViewById(R.id.lv1); List<String> datalist=new LinkedList <>(); datalist.add("大众" ); datalist.add("丰田" ); datalist.add("福特" ); datalist.add("比亚迪" ); datalist.add("哈弗" ); ArrayAdapter adapter=new ArrayAdapter (this , android.R.layout.simple_list_item_single_choice,datalist); mlv.setAdapter(adapter); mlv.addHeaderView(LayoutInflater.from(this ).inflate(R.layout.viewhead,null )); mlv.addFooterView(LayoutInflater.from(this ).inflate(R.layout.viewfoot,null )); mlv.setOnItemClickListener(new AdapterView .OnItemClickListener() { @Override public void onItemClick (AdapterView<?> adapterView, View view, int i, long l) { Toast.makeText(ListViewActivity.this ,i+" Clicked" ,Toast.LENGTH_LONG).show(); } }); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml version="1.0" encoding="utf-8" ?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:app ="http://schemas.android.com/apk/res-auto" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" android:padding ="5dp" tools:context =".listview.ListViewActivity" > <ListView android:id ="@+id/lv1" android:layout_width ="match_parent" android:layout_height ="match_parent" android:divider ="@color/purple_200" android:dividerHeight ="5dp" android:listSelector ="@drawable/listseletor" android:stackFromBottom ="true" android:choiceMode ="multipleChoice" tools:layout_editor_absoluteX ="16dp" tools:layout_editor_absoluteY ="-68dp" /> </androidx.constraintlayout.widget.ConstraintLayout >
1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="utf-8" ?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height ="match_parent" xmlns:app ="http://schemas.android.com/apk/res-auto" > <ImageView android:layout_width ="match_parent" android:layout_height ="100dp" android:gravity ="center" android:background ="@drawable/school" app:layout_constraintTop_toTopOf ="parent" /> </androidx.constraintlayout.widget.ConstraintLayout >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?xml version="1.0" encoding="utf-8" ?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height ="match_parent" xmlns:app ="http://schemas.android.com/apk/res-auto" > <TextView android:layout_width ="match_parent" android:layout_height ="48dp" android:text ="表头" android:textSize ="26sp" android:background ="#FF5722" android:textStyle ="bold" android:textColor ="@color/white" android:gravity ="center" app:layout_constraintTop_toTopOf ="parent" /> </androidx.constraintlayout.widget.ConstraintLayout >
假如使用静态加载数组/链表 ,可以在value目录下创建资源文件,以下以arrays.xml为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?xml version="1.0" encoding="utf-8" ?> <resources > <string-array name ="car" > <item > 别克</item > <item > 宝马</item > <item > 奥迪</item > <item > 奔驰</item > <item > 保时捷</item > <item > 凯迪拉克</item > <item > 劳斯莱斯</item > <item > 法拉利</item > <item > 宾利</item > </string-array > </resources >
BaseAdapter 用baseAdapter实现图文混排步骤
定义行选项的布局格式
自定义一个Adapter,并重写其中的关键方法(四个方法,其中getCout(),getView()是重点)
注册列表选项的单击事件
创建Activity并加载对应的布局文件
1 ps:Layout下的<android:descendantFocusability="blocksDescendants" >可以设置不抢占焦点
测试样例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package com.gallifrey.todayapplication.listview;public class Flower { private int imageId; private String name; private String content; private Boolean checkStatus; public Flower (int imageId,String name,String content) { this .imageId=imageId; this .name=name; this .content=content; checkStatus=false ; } public int getImageId () { return imageId; } public void setImageId (int imageId) { this .imageId = imageId; } public String getName () { return name; } public void setName (String name) { this .name = name; } public String getContent () { return content; } public void setContent (String content) { this .content = content; } public Boolean getCheckStatus () { return checkStatus; } public void setCheckStatus (Boolean checkStatus) { this .checkStatus=checkStatus; } }
FolwerAdapter类和对应xml布局文件(继承自BaseAadpter类)
对getView()方法进行了优化,详情请看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 package com.gallifrey.todayapplication.listview;import android.content.Context;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.CheckBox;import android.widget.CompoundButton;import android.widget.ImageView;import android.widget.TextView;import com.gallifrey.todayapplication.R;import java.nio.channels.ClosedByInterruptException;import java.util.LinkedList;public class FlowerAdapter extends BaseAdapter { private LinkedList<Flower> mDatalist; private Context mContext; private int count=0 ; public FlowerAdapter (LinkedList<Flower> datalist, Context context) { mDatalist=datalist; mContext=context; } @Override public int getCount () { return mDatalist.size(); } @Override public Object getItem (int i) { return mDatalist.get(i); } @Override public long getItemId (int i) { return i; } @Override public View getView (int i, View view, ViewGroup viewGroup) { ViewHolder viewHolder=null ; if (view==null ) { view = LayoutInflater.from(mContext).inflate(R.layout.listitem, viewGroup, false ); viewHolder=new ViewHolder (); viewHolder.item_iv=view.findViewById(R.id.item_iv); viewHolder.item_name=view.findViewById(R.id.item_name); viewHolder.item_content=view.findViewById(R.id.item_content); viewHolder.item_check=view.findViewById(R.id.item_check); view.setTag(viewHolder); count++; }else { viewHolder=(ViewHolder)view.getTag(); } Log.i("Flower" , "getView: 测试一下优化效果 " +count); viewHolder.item_check.setTag(i); viewHolder.item_check.setOnCheckedChangeListener(new CompoundButton .OnCheckedChangeListener() { @Override public void onCheckedChanged (CompoundButton compoundButton, boolean b) { int index=(int )compoundButton.getTag(); mDatalist.get(index).setCheckStatus(b); } }); viewHolder.item_check.setChecked(mDatalist.get(i).getCheckStatus()); viewHolder.item_iv.setImageResource(mDatalist.get(i).getImageId()); viewHolder.item_name.setText(mDatalist.get(i).getName()); viewHolder.item_content.setText(mDatalist.get(i).getContent()); return view; } static class ViewHolder { ImageView item_iv; TextView item_name; TextView item_content; CheckBox item_check; } public void remove (int position) { if (mDatalist!=null ){ mDatalist.remove(position); } notifyDataSetChanged(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <?xml version="1.0" encoding="utf-8" ?> <RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height ="match_parent" android:descendantFocusability ="blocksDescendants" android:paddingHorizontal ="10dp" > <CheckBox android:layout_width ="wrap_content" android:layout_height ="100dp" android:gravity ="center_vertical" android:button ="@drawable/checkbox_bg_round" android:buttonTint ="@drawable/checkbox_color_round" android:id ="@+id/item_check" /> <ImageView android:id ="@+id/item_iv" android:layout_width ="100dp" android:layout_height ="100dp" android:layout_marginStart ="15dp" android:layout_toEndOf ="@id/item_check" android:scaleType ="centerCrop" /> <TextView android:layout_width ="match_parent" android:layout_height ="wrap_content" android:layout_marginTop ="15dp" android:id ="@+id/item_name" android:layout_toEndOf ="@id/item_iv" android:layout_marginStart ="15dp" android:textSize ="26sp" android:textStyle ="bold" /> <TextView android:id ="@+id/item_content" android:layout_width ="match_parent" android:layout_height ="wrap_content" android:layout_below ="@id/item_name" android:layout_marginTop ="15dp" android:layout_alignStart ="@id/item_name" android:textSize ="26sp" /> </RelativeLayout >
在ListView中添加FlowerAdapter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 package com.gallifrey.todayapplication.listview;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.Toast;import com.gallifrey.todayapplication.R;import java.util.LinkedList;import java.util.List;public class ListViewActivity extends AppCompatActivity { private ListView mlv; private List<Flower> flowerList; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_list_view); mlv=findViewById(R.id.lv1); initFlower(); FlowerAdapter flowerAdapter=new FlowerAdapter ((LinkedList<Flower>) flowerList,this ); mlv.setAdapter(flowerAdapter); mlv.setOnItemClickListener(new AdapterView .OnItemClickListener() { @Override public void onItemClick (AdapterView<?> adapterView, View view, int i, long l) { flowerAdapter.remove(i); Toast.makeText(ListViewActivity.this ,i+" Clicked" ,Toast.LENGTH_LONG).show(); } }); } private void initFlower () { flowerList=new LinkedList <>(); flowerList.add(new Flower (R.drawable.baihe,"百合" ,"百年好合" )); flowerList.add(new Flower (R.drawable.rose,"红玫瑰" ,"富有热情" )); flowerList.add(new Flower (R.drawable.yinghua,"樱花" ,"幸福永远" )); flowerList.add(new Flower (R.drawable.sunflower,"向日葵" ,"光辉忠诚" )); flowerList.add(new Flower (R.drawable.ziluolan,"紫罗兰" ,"永恒的美与爱" )); flowerList.add(new Flower (R.drawable.jidanhua,"鸡蛋花" ,"孕育希望复活" )); flowerList.add(new Flower (R.drawable.baihe,"百合22" ,"百年好合" )); flowerList.add(new Flower (R.drawable.rose,"红玫瑰22" ,"富有热情" )); flowerList.add(new Flower (R.drawable.yinghua,"樱花22" ,"幸福永远" )); flowerList.add(new Flower (R.drawable.sunflower,"向日葵22" ,"光辉忠诚" )); flowerList.add(new Flower (R.drawable.ziluolan,"紫罗兰22" ,"永恒的美与爱" )); flowerList.add(new Flower (R.drawable.jidanhua,"鸡蛋花22" ,"孕育希望复活" )); } }
ListView多布局
实现多布局步骤:
定义行选项的布局格式
自定义一个Adapter,并重写其中的关键方法
为ListView设置适配器
测试样例代码 效果预览 PersonChat类 MultiLayoutAdapter类 ListView类 listitem_left.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package com.gallifrey.todayapplication.listview;public class PersonChat { private int imageId; private String words; private Boolean status; public PersonChat (int imageId,String words,Boolean status) { this .imageId=imageId; this .words=words; this .status=status; } public int getImageId () { return imageId; } public void setImageId (int imageId) { this .imageId = imageId; } public String getWords () { return words; } public void setWords (String words) { this .words = words; } public Boolean getStatus () { return status; } public void setStatus (Boolean status) { this .status = status; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 package com.gallifrey.todayapplication.listview;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.gallifrey.todayapplication.R;import java.util.List;public class MultiLayoutAdapter extends BaseAdapter { private static final int TYPE_LEFT=0 ; private static final int TYPE_RIGHT=1 ; private List<PersonChat> mData; private Context mContext; public MultiLayoutAdapter (List<PersonChat> data,Context context) { mData=data; mContext=context; } @Override public int getCount () { return mData.size(); } @Override public Object getItem (int i) { return mData.get(i); } @Override public long getItemId (int i) { return i; } static class ViewHolder { ImageView imageView; TextView textView; } @Override public View getView (int i, View view, ViewGroup viewGroup) { int type=getItemViewType(i); ViewHolder viewHolder=null ; if (view==null ){ switch (type){ case TYPE_LEFT: view= LayoutInflater.from(mContext).inflate(R.layout.listitem_left,viewGroup,false ); break ; case TYPE_RIGHT: view= LayoutInflater.from(mContext).inflate(R.layout.listitem_right,viewGroup,false ); break ; } viewHolder =new ViewHolder (); viewHolder.imageView=view.findViewById(R.id.item_iv); viewHolder.textView=view.findViewById(R.id.item_tv); view.setTag(viewHolder); }else { viewHolder= (ViewHolder) view.getTag(); } viewHolder.imageView.setImageResource(mData.get(i).getImageId()); viewHolder.textView.setText(mData.get(i).getWords()); return view; } @Override public int getViewTypeCount () { return 2 ; } @Override public int getItemViewType (int position) { if (mData.get(position).getStatus()){ return TYPE_RIGHT; }else { return TYPE_LEFT; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 package com.gallifrey.todayapplication.listview;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.Toast;import com.gallifrey.todayapplication.R;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;public class ListViewActivity extends AppCompatActivity { private ListView mlv; private List<Flower> flowerList; private List<PersonChat> personChatList; private static final int TYPE_LEFT=0 ; private static final int TYPE_RIGHT=1 ; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_list_view); mlv=findViewById(R.id.lv1); intiPersonChat(); mlv.setAdapter(new MultiLayoutAdapter (personChatList,this )); } private void intiPersonChat () { personChatList=new ArrayList <>(); for (int i=0 ;i<20 ;i++){ switch ((int )(Math.random()*2 )){ case TYPE_LEFT: personChatList.add(new PersonChat (R.drawable.left_img,"LE" +i,false )); break ; case TYPE_RIGHT: personChatList.add(new PersonChat (R.drawable.right_img,"RE" +i,true )); break ; }; } }; }
listitem_right布局和listitem_left只有位置上有镜像区别,这里就不重复给出了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?xml version="1.0" encoding="utf-8" ?> <RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height ="match_parent" > <ImageView android:layout_width ="64dp" android:layout_height ="64dp" android:id ="@+id/item_iv" android:scaleType ="centerCrop" /> <TextView android:id ="@+id/item_tv" android:layout_width ="158dp" android:layout_height ="62dp" android:layout_marginStart ="3dp" android:layout_toEndOf ="@id/item_iv" android:background ="@mipmap/left_dialog" android:gravity ="center" android:textSize ="26sp" /> </RelativeLayout >
GridView GridView网格视图
用于按行和列的分布方式来显示多个组件
通过Adapter来提供显示数据
XML属性
功能描述
android:numColumns
设置列数
android:columnWidth
设置每一列的宽度
android:stretchMode
设置拉伸模式
android:verticalSpacing
设置各个元素之间的垂直边距
android:horizontalSpacing
设置各个元素之间的水平边距
GridView本地数据显示
创建GridView的步骤:
·在布局文件中使用<GridView>
元素来定义GridView组件
自定义一个Adapter,并重写其中的关键方法
为GridView设置适配器
测试样例代码 效果预览 GirdViewAcitivity类 GirdFlowerAdapter类 activity_grid_view.xml griditem.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 package com.gallifrey.todayapplication.gridview;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.widget.GridView;import com.gallifrey.todayapplication.R;import com.gallifrey.todayapplication.listview.Flower;import java.util.LinkedList;import java.util.List;public class GridViewActivity extends AppCompatActivity { private GridView mGv; private List<Flower> flowerList; public GridViewActivity () { } @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_grid_view); mGv=findViewById(R.id.gv); initFlower(); mGv.setAdapter(new GridFlowerAdapter (flowerList,this )); } private void initFlower () { flowerList=new LinkedList <>(); flowerList.add(new Flower (R.drawable.baihe,"百合" ,"百年好合" )); flowerList.add(new Flower (R.drawable.rose,"红玫瑰" ,"富有热情" )); flowerList.add(new Flower (R.drawable.yinghua,"樱花" ,"幸福永远" )); flowerList.add(new Flower (R.drawable.sunflower,"向日葵" ,"光辉忠诚" )); flowerList.add(new Flower (R.drawable.ziluolan,"紫罗兰" ,"永恒的美与爱" )); flowerList.add(new Flower (R.drawable.jidanhua,"鸡蛋花" ,"孕育希望复活" )); flowerList.add(new Flower (R.drawable.baihe,"百合22" ,"百年好合" )); flowerList.add(new Flower (R.drawable.rose,"红玫瑰22" ,"富有热情" )); flowerList.add(new Flower (R.drawable.yinghua,"樱花22" ,"幸福永远" )); flowerList.add(new Flower (R.drawable.sunflower,"向日葵22" ,"光辉忠诚" )); flowerList.add(new Flower (R.drawable.ziluolan,"紫罗兰22" ,"永恒的美与爱" )); flowerList.add(new Flower (R.drawable.jidanhua,"鸡蛋花22" ,"孕育希望复活" )); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 package com.gallifrey.todayapplication.gridview;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.gallifrey.todayapplication.R;import com.gallifrey.todayapplication.listview.Flower;import java.util.List;public class GridFlowerAdapter extends BaseAdapter { private List<Flower> mData; private Context mContext; public GridFlowerAdapter (List<Flower> data,Context context) { mData=data; mContext=context; } @Override public int getCount () { return mData.size(); } @Override public Object getItem (int i) { return mData.get(i); } @Override public long getItemId (int i) { return i; } @Override public View getView (int i, View view, ViewGroup viewGroup) { ViewHolder viewHolder=null ; if (view==null ){ view= LayoutInflater.from(mContext).inflate(R.layout.griditem,viewGroup,false ); viewHolder=new ViewHolder (); viewHolder.imageView=view.findViewById(R.id.gv_iv); viewHolder.textView=view.findViewById(R.id.gv_tv); view.setTag(viewHolder); }else { viewHolder= (ViewHolder) view.getTag(); } viewHolder.imageView.setImageResource(mData.get(i).getImageId()); viewHolder.textView.setText(mData.get(i).getName()); return view; } static class ViewHolder { ImageView imageView; TextView textView; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?xml version="1.0" encoding="utf-8" ?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:app ="http://schemas.android.com/apk/res-auto" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" tools:context =".gridview.GridViewActivity" > <GridView android:layout_width ="match_parent" android:layout_height ="match_parent" android:id ="@+id/gv" android:numColumns ="3" android:horizontalSpacing ="10dp" /> </androidx.constraintlayout.widget.ConstraintLayout >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <?xml version="1.0" encoding="utf-8" ?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height ="wrap_content" xmlns:app ="http://schemas.android.com/apk/res-auto" > <ImageView android:layout_width ="match_parent" android:layout_height ="200dp" android:id ="@+id/gv_iv" android:src ="@drawable/baihe" app:layout_constraintTop_toTopOf ="parent" android:scaleType ="centerCrop" app:layout_constraintBottom_toTopOf ="@id/gv_tv" /> <TextView android:layout_width ="match_parent" android:layout_height ="wrap_content" android:id ="@+id/gv_tv" android:textSize ="26sp" android:text ="test" android:gravity ="center" android:layout_marginTop ="10dp" app:layout_constraintTop_toBottomOf ="@id/gv_iv" app:layout_constraintBottom_toBottomOf ="parent" /> </androidx.constraintlayout.widget.ConstraintLayout >
GridView网络数据显示
使用步骤:
设置网络权限,在AndroidManifest.xml文件中添加<uses-permission android:name="android.permission.INTERNET"/>
添加glide依赖,并同步,GitHub链接bumptech/glide
1 2 3 4 dependencies { implementation 'com.github.bumptech.glide:glide:4.13.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0' }
使用Glide类添加图片
测试样例代码 效果预览 GirdViewAcitivity类 GirdFlowerAdapter类 activity_grid_view.xml griditem.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 package com.gallifrey.todayapplication.gridview;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.widget.GridView;import com.gallifrey.todayapplication.R;import com.gallifrey.todayapplication.listview.Flower;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;public class GridViewActivity extends AppCompatActivity { private GridView mGv; private List<Flower> flowerList; private List<String> imgNetList; public GridViewActivity () { } @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_grid_view); mGv=findViewById(R.id.gv); initImageNet(); mGv.setAdapter(new GridFlowerAdapter (imgNetList,this )); } private void initImageNet () { imgNetList=new ArrayList <>(); imgNetList.add("https://gallifrey.asia/img/kyueki01.webp" ); imgNetList.add("https://gallifrey.asia/img/kyueki02.webp" ); imgNetList.add("https://gallifrey.asia/img/kyueki03.webp" ); imgNetList.add("https://gallifrey.asia/img/kyueki04.webp" ); imgNetList.add("https://gallifrey.asia/img/kyueki05.webp" ); imgNetList.add("https://gallifrey.asia/img/kyueki06.webp" ); imgNetList.add("https://gallifrey.asia/img/kyueki07.webp" ); imgNetList.add("https://gallifrey.asia/img/kyueki08.webp" ); imgNetList.add("https://gallifrey.asia/img/kyueki09.webp" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 package com.gallifrey.todayapplication.gridview;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.bumptech.glide.Glide;import com.bumptech.glide.load.engine.DiskCacheStrategy;import com.gallifrey.todayapplication.R;import com.gallifrey.todayapplication.listview.Flower;import java.util.List;public class GridFlowerAdapter extends BaseAdapter { private List<String> mData; private Context mContext; public GridFlowerAdapter (List<String> data,Context context) { mData=data; mContext=context; } @Override public int getCount () { return mData.size(); } @Override public Object getItem (int i) { return mData.get(i); } @Override public long getItemId (int i) { return i; } @Override public View getView (int i, View view, ViewGroup viewGroup) { ViewHolder viewHolder=null ; if (view==null ){ view= LayoutInflater.from(mContext).inflate(R.layout.griditem,viewGroup,false ); viewHolder=new ViewHolder (); viewHolder.imageView=view.findViewById(R.id.gv_iv); viewHolder.textView=view.findViewById(R.id.gv_tv); view.setTag(viewHolder); }else { viewHolder= (ViewHolder) view.getTag(); } Glide.with(mContext) .load(mData.get(i)) .centerCrop() .placeholder(R.mipmap.ic_launcher) .diskCacheStrategy(DiskCacheStrategy.NONE) .into(viewHolder.imageView); viewHolder.textView.setText("图片" +i); return view; } static class ViewHolder { ImageView imageView; TextView textView; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?xml version="1.0" encoding="utf-8" ?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:app ="http://schemas.android.com/apk/res-auto" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" tools:context =".gridview.GridViewActivity" > <GridView android:layout_width ="match_parent" android:layout_height ="match_parent" android:id ="@+id/gv" android:numColumns ="2" android:horizontalSpacing ="10dp" /> </androidx.constraintlayout.widget.ConstraintLayout >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?xml version="1.0" encoding="utf-8" ?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height ="wrap_content" xmlns:app ="http://schemas.android.com/apk/res-auto" > <ImageView android:layout_width ="match_parent" android:layout_height ="200dp" android:id ="@+id/gv_iv" app:layout_constraintTop_toTopOf ="parent" android:scaleType ="centerCrop" app:layout_constraintBottom_toTopOf ="@id/gv_tv" /> <TextView android:layout_width ="match_parent" android:layout_height ="wrap_content" android:id ="@+id/gv_tv" android:textSize ="26sp" android:gravity ="center" android:layout_marginTop ="10dp" app:layout_constraintTop_toBottomOf ="@id/gv_iv" app:layout_constraintBottom_toBottomOf ="parent" /> </androidx.constraintlayout.widget.ConstraintLayout >
RecyclerView 简介
使用:
设置Adapter
设置LayoutManager
RecyclerView提供了三种布局管理器:
LinerLayoutManager 以垂直或者水平列表方式展示Item
GridLayoutManager 以网格方式展示Item
StaggeredGridLayoutManager 以瀑布流方式展示Item
测试样例代码 效果预览 自定义Adapter类 Activity类 实体类 Activity布局文件 item布局文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package com.gallifrey.todayapplication.recyclerview;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import androidx.annotation.NonNull;import androidx.recyclerview.widget.RecyclerView;import com.gallifrey.todayapplication.R;import com.gallifrey.todayapplication.listview.Flower;import java.util.List;public class RecyclerFlowerAdapter extends RecyclerView .Adapter<RecyclerFlowerAdapter.ViewHolder>{ private List<Flower> mData; private Context mContext; public RecyclerFlowerAdapter (List<Flower> mData, Context mContext) { this .mData = mData; this .mContext = mContext; } static class ViewHolder extends RecyclerView .ViewHolder{ ImageView imageView; TextView textView; public ViewHolder (@NonNull View itemView) { super (itemView); imageView=itemView.findViewById(R.id.rv_iv); textView=itemView.findViewById(R.id.rv_tv); } } @NonNull @Override public RecyclerFlowerAdapter.ViewHolder onCreateViewHolder (@NonNull ViewGroup parent, int viewType) { View view=LayoutInflater.from(mContext).inflate(R.layout.recyclershitem,parent,false ); ViewHolder viewHolder = new ViewHolder (view); return viewHolder; } @Override public void onBindViewHolder (@NonNull RecyclerFlowerAdapter.ViewHolder holder, int position) { holder.imageView.setImageResource(mData.get(position).getImageId()); holder.textView.setText(mData.get(position).getName()); } @Override public int getItemCount () { return mData.size(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 package com.gallifrey.todayapplication.recyclerview;import androidx.appcompat.app.AppCompatActivity;import androidx.recyclerview.widget.GridLayoutManager;import androidx.recyclerview.widget.LinearLayoutManager;import androidx.recyclerview.widget.RecyclerView;import androidx.recyclerview.widget.StaggeredGridLayoutManager;import android.os.Bundle;import android.widget.GridLayout;import android.widget.LinearLayout;import com.gallifrey.todayapplication.R;import com.gallifrey.todayapplication.listview.Flower;import java.util.LinkedList;import java.util.List;public class RecyclerViewActivity extends AppCompatActivity { private RecyclerView mRv; private List<Flower> flowerList; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_recycle_view); initFlower(); mRv=findViewById(R.id.rv); StaggeredGridLayoutManager staggeredGridLayoutManager=new StaggeredGridLayoutManager (2 ,StaggeredGridLayoutManager.HORIZONTAL); mRv.setLayoutManager(staggeredGridLayoutManager); mRv.setAdapter(new RecyclerFlowerAdapter (flowerList,this )); } private void initFlower () { flowerList=new LinkedList <>(); flowerList.add(new Flower (R.drawable.baihe,"百合" ,"百年好合" )); flowerList.add(new Flower (R.drawable.rose,"红玫瑰" ,"富有热情" )); flowerList.add(new Flower (R.drawable.yinghua,"樱花" ,"幸福永远" )); flowerList.add(new Flower (R.drawable.sunflower,"向日葵" ,"光辉忠诚" )); flowerList.add(new Flower (R.drawable.ziluolan,"紫罗兰" ,"永恒的美与爱" )); flowerList.add(new Flower (R.drawable.jidanhua,"鸡蛋花" ,"孕育希望复活" )); flowerList.add(new Flower (R.drawable.baihe,"百合22" ,"百年好合" )); flowerList.add(new Flower (R.drawable.rose,"红玫瑰22" ,"富有热情" )); flowerList.add(new Flower (R.drawable.yinghua,"樱花22" ,"幸福永远" )); flowerList.add(new Flower (R.drawable.sunflower,"向日葵22" ,"光辉忠诚" )); flowerList.add(new Flower (R.drawable.ziluolan,"紫罗兰22" ,"永恒的美与爱" )); flowerList.add(new Flower (R.drawable.jidanhua,"鸡蛋花22" ,"孕育希望复活" )); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package com.gallifrey.todayapplication.listview;public class Flower { private int imageId; private String name; private String content; private Boolean checkStatus; public Flower (int imageId,String name,String content) { this .imageId=imageId; this .name=name; this .content=content; checkStatus=false ; } public int getImageId () { return imageId; } public void setImageId (int imageId) { this .imageId = imageId; } public String getName () { return name; } public void setName (String name) { this .name = name; } public String getContent () { return content; } public void setContent (String content) { this .content = content; } public Boolean getCheckStatus () { return checkStatus; } public void setCheckStatus (Boolean checkStatus) { this .checkStatus=checkStatus; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="utf-8" ?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:app ="http://schemas.android.com/apk/res-auto" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" tools:context =".recyclerview.RecyclerViewActivity" > <androidx.recyclerview.widget.RecyclerView android:layout_width ="match_parent" android:layout_height ="match_parent" android:id ="@+id/rv" /> </androidx.constraintlayout.widget.ConstraintLayout >
recyclerlinearitem.xml 线性布局/网格布局
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?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" android:orientation ="vertical" > <ImageView android:layout_width ="match_parent" android:layout_height ="0dp" android:layout_weight ="1" android:id ="@+id/rv_iv" android:src ="@drawable/baihe" android:scaleType ="centerCrop" /> <TextView android:layout_width ="match_parent" android:layout_height ="wrap_content" android:id ="@+id/rv_tv" android:text ="test" android:textSize ="26sp" android:gravity ="center" android:layout_marginTop ="10dp" /> </LinearLayout >
recyclershitem.xml 瀑布流布局 水平方向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="wrap_content" android:layout_height ="match_parent" android:orientation ="vertical" > <ImageView android:layout_width ="wrap_content" android:layout_height ="0dp" android:layout_weight ="1" android:id ="@+id/rv_iv" android:src ="@drawable/baihe" android:scaleType ="centerCrop" /> <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:id ="@+id/rv_tv" android:text ="test" android:layout_gravity ="center" android:textSize ="26sp" android:gravity ="center" android:layout_marginTop ="10dp" /> </LinearLayout >
recyclersvitem.xml 瀑布流布局 垂直方向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?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 ="wrap_content" android:orientation ="vertical" > <ImageView android:layout_width ="match_parent" android:layout_height ="wrap_content" android:id ="@+id/rv_iv" android:src ="@drawable/baihe" android:scaleType ="centerCrop" /> <TextView android:layout_width ="match_parent" android:layout_height ="wrap_content" android:id ="@+id/rv_tv" android:text ="test" android:textSize ="26sp" android:gravity ="center" android:layout_marginTop ="10dp" /> </LinearLayout >
TabHost与TabLayout TabHost
实现在窗口中放置多个标签页
通常需要与TabWidget、TabSpec组件结合使用
TabWidget:显示TabHost标签页中上部和下部的按钮
TabSpec:选项卡界面
TabHost创建、添加选项卡的方法:
newTabSpec(String tag):创建选项卡
addTab(tabSpec):添加选项卡
继承TabActivity使用TabHost
继承TabActivity时使用TabHost的步骤:
创建一个Activity:继承TabActivity
定义布局: id必须使用系统ID
获取组件: getTabHost()
创建选项卡
不继承TabActivity使用TabHost
不继承TabActivity时使用TabHost的步骤:
创建Activity:不继承TabActivity
定义布局:id可以自定义
获取组件:findViewById()
创建选项卡
TabActivity在Android 3.0以后已过时,推荐使用“不继承TabActivity的方式”使用TabHost
TabLayout Tabhost因为无法实现滑动已经不常用了,现在的实现标签选项卡的方式是TabLayout+ViewPager
什么是TabLayout:
怎么使用:
定义布局,为TabLayout添加tab
定义适配器PagerAdapter
ViewPager设置适配器
TabLayout加载ViewPager
属性和方法
属性
方法
tabIndicatorFullWidth
addTab()
tabRippleColor
getTabAt()
tabTextAppearance
getTabCount()
tabMode
newTab()
tabIndicatorColor
removeAllTabs()
tabIndicatorHeight
removeTab()
tabIndicatorGravity
测试样例代码 viewPager已经停止维护了,这里使用官方推荐的viewPager2
效果预览 Activity类 实体类 适配器类 Fragment类 布局文件 资源样式文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 package com.gallifrey.todayapplication.tablayout;import androidx.annotation.NonNull;import androidx.appcompat.app.AppCompatActivity;import androidx.fragment.app.Fragment;import androidx.fragment.app.FragmentPagerAdapter;import androidx.viewpager.widget.ViewPager;import androidx.viewpager2.widget.ViewPager2;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import com.gallifrey.todayapplication.R;import com.google.android.material.tabs.TabLayout;import com.google.android.material.tabs.TabLayoutMediator;import java.util.ArrayList;import java.util.List;public class TabLayoutActivity extends AppCompatActivity { private TabLayout mTabLayout; private List<IconRelation> iconRelationList; private List<Fragment> fragmentList; private ViewPager2 viewPager2; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_tab_layout); mTabLayout=findViewById(R.id.tab_layout); viewPager2=findViewById(R.id.view_pager2); initIcon(); intiFragment(); viewPager2.setAdapter(new ImageStateAdapter (this ,fragmentList)); new TabLayoutMediator (mTabLayout, viewPager2, new TabLayoutMediator .TabConfigurationStrategy() { @Override public void onConfigureTab (@NonNull TabLayout.Tab tab, int position) { tab.setCustomView(getTabView(iconRelationList,position)); } }).attach(); mTabLayout.getTabAt(2 ).select(); mTabLayout.addOnTabSelectedListener(new TabLayout .OnTabSelectedListener() { @Override public void onTabSelected (TabLayout.Tab tab) { View view=tab.getCustomView(); ImageView imageView=view.findViewById(R.id.tab_iv); TextView textView=view.findViewById(R.id.tab_tv); imageView.setSelected(true ); textView.setTextAppearance(R.style.TabSelectedStyle); } @Override public void onTabUnselected (TabLayout.Tab tab) { View view=tab.getCustomView(); ImageView imageView=view.findViewById(R.id.tab_iv); TextView textView=view.findViewById(R.id.tab_tv); imageView.setSelected(false ); textView.setTextAppearance(R.style.TabUnSelectedStyle); } @Override public void onTabReselected (TabLayout.Tab tab) { } }); } private void intiFragment () { fragmentList=new ArrayList <>(); fragmentList.add(MessageFragment.newInstance(R.drawable.laohu)); fragmentList.add(MessageFragment.newInstance(R.drawable.ziluolande)); fragmentList.add(MessageFragment.newInstance(R.drawable.baihe)); fragmentList.add(MessageFragment.newInstance(R.drawable.classroom)); } private View getTabView (List<IconRelation> data,int position) { View view= LayoutInflater.from(this ).inflate(R.layout.tab_item,null ); ImageView imageView=view.findViewById(R.id.tab_iv); TextView textView=view.findViewById(R.id.tab_tv); imageView.setImageResource(data.get(position).getImageId()); textView.setText(data.get(position).getName()); return view; } private void initIcon () { iconRelationList=new ArrayList <>(); iconRelationList.add(new IconRelation (R.drawable.fl_rb_message_bg,"消息" )); iconRelationList.add(new IconRelation (R.drawable.fl_rb_phone_bg,"通讯" )); iconRelationList.add(new IconRelation (R.drawable.fl_rb_discover_bg,"发现" )); iconRelationList.add(new IconRelation (R.drawable.fl_rb_me_bg,"我的" )); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.gallifrey.todayapplication.tablayout;public class IconRelation { private int imageId; private String name; public IconRelation (int imageId, String name) { this .imageId = imageId; this .name = name; } public int getImageId () { return imageId; } public void setImageId (int imageId) { this .imageId = imageId; } public String getName () { return name; } public void setName (String name) { this .name = name; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.gallifrey.todayapplication.tablayout;import androidx.annotation.NonNull;import androidx.fragment.app.Fragment;import androidx.fragment.app.FragmentActivity;import androidx.viewpager2.adapter.FragmentStateAdapter;import java.util.List;public class ImageStateAdapter extends FragmentStateAdapter { private List<Fragment>fragmentList; public ImageStateAdapter (@NonNull FragmentActivity fragmentActivity, List<Fragment> fragmentList) { super (fragmentActivity); this .fragmentList=fragmentList; } @NonNull @Override public Fragment createFragment (int position) { return fragmentList.get(position); } @Override public int getItemCount () { return fragmentList.size(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 package com.gallifrey.todayapplication.tablayout;import android.os.Bundle;import androidx.fragment.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import com.gallifrey.todayapplication.R;public class MessageFragment extends Fragment { private static final String ARG_PARAM1 = "param1" ; private int mParam1; public MessageFragment () { } public static MessageFragment newInstance (int param1) { MessageFragment fragment = new MessageFragment (); Bundle args = new Bundle (); args.putInt(ARG_PARAM1, param1); fragment.setArguments(args); return fragment; } @Override public void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); if (getArguments() != null ) { mParam1 = getArguments().getInt(ARG_PARAM1); } } @Override public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view= inflater.inflate(R.layout.fragment_message2, container, false ); ImageView imageView=view.findViewById(R.id.fl_iv); imageView.setImageResource(mParam1); return view; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 <?xml version="1.0" encoding="utf-8" ?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:app ="http://schemas.android.com/apk/res-auto" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" tools:context =".tablayout.TabLayoutActivity" > <com.google.android.material.tabs.TabLayout app:tabIndicatorColor ="#05d236" app:tabIndicatorHeight ="5dp" app:tabIndicatorFullWidth ="false" app:tabTextColor ="#6F392727" app:tabSelectedTextColor ="#05d236" app:tabTextAppearance ="@style/TabStyle" android:id ="@+id/tab_layout" android:layout_width ="match_parent" android:layout_height ="wrap_content" app:layout_constraintStart_toStartOf ="parent" app:layout_constraintTop_toTopOf ="parent" > </com.google.android.material.tabs.TabLayout > <androidx.viewpager2.widget.ViewPager2 android:id ="@+id/view_pager2" android:layout_width ="match_parent" android:layout_height ="0dp" app:layout_constraintVertical_weight ="1" app:layout_constraintTop_toBottomOf ="@id/tab_layout" /> </androidx.constraintlayout.widget.ConstraintLayout >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?xml version="1.0" encoding="utf-8" ?> <FrameLayout 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" tools:context =".tablayout.MessageFragment" > <ImageView android:layout_width ="match_parent" android:layout_height ="match_parent" android:id ="@+id/fl_iv" android:scaleType ="centerCrop" /> </FrameLayout >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?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" android:orientation ="vertical" android:padding ="5dp" > <TextView android:layout_width ="48dp" android:layout_height ="wrap_content" android:id ="@+id/tab_tv" android:text ="测试" android:textColor ="#a5a5a5" android:textSize ="20sp" /> <ImageView android:layout_width ="48dp" android:layout_height ="48dp" android:id ="@+id/tab_iv" android:scaleType ="center" android:src ="@drawable/fl_rb_message_bg" /> </LinearLayout >
在values文件夹下新建styles.xml文件添加字体选中效果样式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?xml version="1.0" encoding="utf-8" ?> <resources > <style name ="TabStyle" > <item name ="android:textSize" > 30sp</item > <item name ="android:textStyle" > bold</item > </style > <style name ="TabSelectedStyle" > <item name ="android:textColor" > #05d236</item > <item name ="android:textStyle" > bold</item > </style > <style name ="TabUnSelectedStyle" > <item name ="android:textColor" > #a5a5a5</item > <item name ="android:textStyle" > normal</item > </style > </resources >
drawable文件夹下添加图标变化的样式,写法一样这里给出一个样例(其实就是设置两张照片,选中时为有色图标,非选中为灰色图标)
1 2 3 4 5 <?xml version="1.0" encoding="utf-8" ?> <selector xmlns:android ="http://schemas.android.com/apk/res/android" > <item android:state_selected ="true" android:drawable ="@mipmap/discover2" /> <item android:state_selected ="false" android:drawable ="@mipmap/discover" /> </selector >
WebView 基础知识
WebView用于在App中加载网页
使用Web检查器来调试HTML、CSS、Javascript等代码
可以对URL请求、页面加载、渲染以及页面的交互进行处理
WebView具有以下几个辅助类:
WebChromeClient:辅助WebView实现与浏览器的交互动作
WebViewClient:帮助WebView处理各种通知、请求事件等
WebSettings:对WebView进行配置和管理
addJavascriptInterface():将Java对象绑定到WebView中,以便JavaScript从页面中控制Java对象,实现WebView与HTML页面的交互
使用WebView的步骤
WebView使用介绍
测试样例代码 示例中实现了WebView与JavaScript的交互,以及WebView和Activity的交互
效果预览 修改设置 自定义html Activity类 布局文件
如果要应用访问网络网站,而且能通过明文网址访问,要修改AndroidManifest.xml文件相关设置
加入联网许可
1 <uses-permission android:name ="android.permission.INTERNET" />
1 2 <application android:usesCleartextTraffic ="true" />
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <html > <head > <title > Welcome to Webview</title > </head > <body > <center > <div style ="margin-top:10%; font-size:30" > Js调用Android</div > <button style ="margin-top:10%; width:160;height:60;font-size:30" onclick ="android.login()" > 登陆</button > <h1 style ="margin-top:10%" id ="username" > </h1 > </center > <script > function showUserName (username ){ document .getElementById ("username" ).innerText ="登录名:" +username; } </script > </body > </html >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 package com.gallifrey.todayapplication.webview;import androidx.activity.result.ActivityResult;import androidx.activity.result.ActivityResultCallback;import androidx.activity.result.ActivityResultLauncher;import androidx.activity.result.contract.ActivityResultContract;import androidx.activity.result.contract.ActivityResultContracts;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;import android.graphics.Bitmap;import android.net.http.SslError;import android.os.Bundle;import android.view.KeyEvent;import android.webkit.JavascriptInterface;import android.webkit.SslErrorHandler;import android.webkit.WebChromeClient;import android.webkit.WebSettings;import android.webkit.WebView;import android.webkit.WebViewClient;import android.widget.TextView;import com.gallifrey.todayapplication.R;public class WebViewActivity extends AppCompatActivity { private WebView mWebview; private ActivityResultLauncher mLauncher; private TextView mTvTitle,mTvStart,mTvFinish,mTvProgress; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_web_view); mLauncher=registerForActivityResult(new ActivityResultContracts .StartActivityForResult(), new ActivityResultCallback <ActivityResult>() { @Override public void onActivityResult (ActivityResult result) { if (result.getResultCode()==1 ){ String tt=result.getData().getStringExtra("user" ); mWebview.loadUrl("javascript:showUserName('" +tt+" new')" ); } } }); mTvTitle=findViewById(R.id.webview_tv_title); mTvStart=findViewById(R.id.webview_tv_start); mTvFinish=findViewById(R.id.webview_tv_finish); mTvProgress=findViewById(R.id.webview_tv_progress); mWebview=findViewById(R.id.web_view); mWebview.setWebViewClient(new WebViewClient (){ @Override public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { super .onReceivedSslError(view, handler, error); handler.proceed(); } @Override public boolean shouldOverrideUrlLoading (WebView view, String url) { return false ; } @Override public void onPageStarted (WebView view, String url, Bitmap favicon) { super .onPageStarted(view, url, favicon); mTvStart.setText("开始加载" ); } @Override public void onPageFinished (WebView view, String url) { super .onPageFinished(view, url); mTvFinish.setText("加载完成" ); } }); mWebview.setWebChromeClient(new WebChromeClient (){ @Override public void onReceivedTitle (WebView view, String title) { super .onReceivedTitle(view, title); mTvTitle.setText(title); } @Override public void onProgressChanged (WebView view, int newProgress) { super .onProgressChanged(view, newProgress); if (newProgress<100 ){ mTvProgress.setText(newProgress+"%" ); }else { mTvProgress.setText("100%" ); } } }); WebSettings webSettings=mWebview.getSettings(); webSettings.setJavaScriptEnabled(true ); webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); mWebview.addJavascriptInterface(this ,"android" ); mWebview.loadUrl("file:///android_asset/test.html" ); } @JavascriptInterface public void login () { Intent intent=new Intent (this ,LoginActivity.class); mLauncher.launch(intent); } @Override public boolean onKeyDown (int keyCode, KeyEvent event) { if (keyCode==KeyEvent.KEYCODE_BACK&&mWebview.canGoBack()){ mWebview.goBack(); return true ; } return super .onKeyDown(keyCode, event); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.gallifrey.todayapplication.webview;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.EditText;import com.gallifrey.todayapplication.R;public class LoginActivity extends AppCompatActivity { private EditText mEtUser; private Button mBtnSubmit; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_login); mEtUser=findViewById(R.id.webview_et_user); mBtnSubmit=findViewById(R.id.webview_btn_submit); mBtnSubmit.setOnClickListener(new View .OnClickListener() { @Override public void onClick (View view) { String temp=mEtUser.getText().toString(); Intent data=new Intent (); data.putExtra("user" ,temp); setResult(1 ,data); finish(); } }); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 <?xml version="1.0" encoding="utf-8" ?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:app ="http://schemas.android.com/apk/res-auto" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" tools:context =".webview.WebViewActivity" > <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:id ="@+id/webview_tv_title" android:text ="标题" android:textSize ="26sp" app:layout_constraintStart_toStartOf ="parent" app:layout_constraintTop_toTopOf ="parent" app:layout_constraintBottom_toTopOf ="@id/webview_tv_start" /> <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:id ="@+id/webview_tv_start" android:text ="开始" android:textSize ="26sp" app:layout_constraintStart_toStartOf ="parent" app:layout_constraintTop_toBottomOf ="@id/webview_tv_title" app:layout_constraintBottom_toTopOf ="@id/webview_tv_finish" /> <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:id ="@+id/webview_tv_finish" android:text ="结束" android:textSize ="26sp" app:layout_constraintStart_toStartOf ="parent" app:layout_constraintTop_toBottomOf ="@id/webview_tv_start" app:layout_constraintBottom_toTopOf ="@id/webview_tv_progress" /> <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:id ="@+id/webview_tv_progress" android:text ="进度" android:textSize ="26sp" app:layout_constraintStart_toStartOf ="parent" app:layout_constraintTop_toBottomOf ="@id/webview_tv_finish" app:layout_constraintBottom_toTopOf ="@id/web_view" /> <WebView android:layout_width ="match_parent" android:layout_height ="0dp" android:id ="@+id/web_view" app:layout_constraintVertical_weight ="1" app:layout_constraintStart_toStartOf ="parent" app:layout_constraintTop_toBottomOf ="@id/webview_tv_progress" app:layout_constraintBottom_toBottomOf ="parent" /> </androidx.constraintlayout.widget.ConstraintLayout >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 <?xml version="1.0" encoding="utf-8" ?> <RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:app ="http://schemas.android.com/apk/res-auto" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:paddingTop ="10dp" android:paddingStart ="10dp" android:paddingEnd ="10dp" tools:context =".EditTextActivity" > <TextView android:layout_marginTop ="200dp" android:id ="@+id/webview_tv_user" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="用户名: " android:textSize ="30sp" /> <EditText android:id ="@+id/webview_et_user" android:layout_width ="match_parent" android:layout_height ="wrap_content" android:layout_alignBaseline ="@id/webview_tv_user" android:layout_toEndOf ="@id/webview_tv_user" android:background ="@drawable/bgeditext" android:hint ="请输入号码" android:inputType ="phone" android:paddingStart ="10dp" android:textSize ="30sp" /> <TextView android:id ="@+id/webview_tv_pwd" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:layout_below ="@id/webview_tv_user" android:layout_alignStart ="@id/webview_tv_user" android:layout_marginTop ="40dp" android:text ="密 码: " android:textSize ="30sp" /> <EditText android:id ="@+id/webview_et_pwd" android:layout_width ="match_parent" android:layout_height ="wrap_content" android:layout_below ="@id/webview_et_user" android:layout_alignBaseline ="@id/webview_tv_pwd" android:layout_toEndOf ="@id/webview_tv_pwd" android:background ="@drawable/bgeditext" android:drawablePadding ="5dp" android:hint ="请输入密码" android:inputType ="textPassword" android:paddingStart ="10dp" android:textSize ="30sp" /> <Button android:id ="@+id/webview_btn_submit" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:layout_below ="@id/webview_tv_pwd" android:layout_centerHorizontal ="true" android:layout_marginTop ="40dp" android:background ="@drawable/pressresult" android:paddingHorizontal ="60dp" android:text ="确定" android:textSize ="30sp" /> </RelativeLayout >