文章目录
1、基础控件
1、TextView
TextView作为最常用的控件之一, 也是我们接触最早的一个控件
在TextView 中 有几个常用的属性
android:id :用于给控件添加唯一标识符
android:layout_width:用于设置宽度
android:layout_height:用于设置高度
android:text:用于设置显示的文字
android:gravity:用于设置控件对齐方式
2、Button
Button是程序和用户进行交互的一个重要控件 Button继承自TextView
因此TextView 绝大部分属性 Button 也是拥有的
Button 中会将android:text 属性中所录入字母字符转换成大写方式
我们可以通过 android:textAllCaps=“false” 取消转换
3、EditText
EidtText 的应用非常普遍 例如登录或者编辑文本都会使用
EditText常用属性
android:hint :用于设置提示性的文本
android:maxLines:用于设置最大行数
我们可以通过 .getText.toString() 方法获取文本中内容
4、ImageView
ImageView其核心属性 Src 用于设置图片来源
只需要将图片赋值粘贴到Drawable 文件中即可
我们通过 scaleType 属性即可设置图片和和父级元素的显示方式
5、ProgressBar
ProgressBar 用于显示一个进度条
一般我们在加载数据时便会用到这个控件
我们会通过 visibility 对该控件进行指定可见属性
visibility 默认值为visible 可见
invisible 为不可见 但是还是会占据原本的控件
而 gone 则是不可见 并且取消当前所占的控件
我们再代码中可以通过 setVisibility()方法传入
【View.VISIBLE】【Vew.INVISIBLE】【View.GONE】三种值来指定
点击消失与出现的代码如下
public void Progress_Visiblity_onclick(View view) {
ProgressBar progressBar=findViewById(R.id.progressBay);
if (progressBar.getVisibility()==View.VISIBLE){
progressBar.setVisibility(View.INVISIBLE);
}else {
progressBar.setVisibility(View.VISIBLE);
}
}
我们还可以指定不同样式的进度条
例如使用
【style=“@style/Widget.AppCompat.ProgressBar.Horizontal”】
则可以将整体进度条样式修改成 条形加载条
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="50dp"/>
助力加载案例实现
public void ProgressBar_Wight_onClick(View view) {
Button btn=findViewById(R.id.Button_Progress_wigth);
ProgressBar progressBar=findViewById(R.id.Horizontal_ProgressBar);
int i = (progressBar.getProgress() + 10);
progressBar.setProgress(i);
if (progressBar.getProgress()==100){
Toast.makeText(this,"助力成功",Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.INVISIBLE);
btn.setText("已助力成功");
btn.setEnabled(false);
}
}
6、AlertDialog
这是一个中以提示窗口 出现的控件
我们在其中设置 窗体的标题 和 内容 和点击事件 和是否能被取消 以及点击事件
完善ProgressBar显示与取消 代码如下
public void Progress_Visiblity_onclick(View view) {
ProgressBar progressBar=findViewById(R.id.progressBay);
// 实例化一个 AlerDialog.BUilder
if (progressBar.getVisibility()==View.VISIBLE){
AlertDialog.Builder dialog=new AlertDialog.Builder(this);
dialog.setTitle("提示");
dialog.setMessage("您确定要取消取消加载吗?");
dialog.setCancelable(false);
// 设置确定 之后的点击事件
dialog.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
progressBar.setVisibility(View.INVISIBLE);
}
});
// 设置取消后的点击事件
dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
dialog.show();
}else {
AlertDialog.Builder dialog=new AlertDialog.Builder(this);
dialog.setTitle("提示");
dialog.setMessage("您确定要重新加载吗");
// 设置能否被 back 键 或者点击空白处消取提示框
dialog.setCancelable(false);
// 设置取消的点击事件
dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
// 设置确定的点击事件
dialog.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
progressBar.setVisibility(View.VISIBLE);
}
});
dialog.show();
}
}
dialog.setCancelable(false); 2种方式都不能使得对话框消失 dialog.setCanceledOnTouchOutside(true); 2种方式都可以使得对话框消失 dialog.setCanceledOnTouchOutside(false); 只有手机返回按键可使得对话框消失 dialog.setCancelable(false); dialog.setCanceledOnTouchOutside(false); 2种方式都不能使得对话框消失
AlertDialog的三种点击事件的区别
setPositiveButton 和 setNegativeButton 和 setNeutralButton
三者都是AlertDialog弹出框的按钮,只是显示的位置不同,项目中可根据情况选择使用,setPositiveButton 一般用于确认,setNegativeButton一般用于取消,setNeutralButton 这个是相当于一个忽略操作的按钮。
————————————————
7、ProgressDialog
该控件也是通过 代码实现并且该控件的整体设置于 AlertDialog 相似
但是如果 setCancelable 其属性为 False 那么 我们的在加载数据之后 一定要通过 ProgressDialog.Dismiss() 从而关闭 提示框
整体代码如下
public void OnClick(View view){
// 实例化 ProgressDialog
ProgressDialog dialog=new ProgressDialog(this);
dialog.setTitle("提示");
dialog.Messages("Loading....");
dialog.setCanceLable(true);
dialog.show();
}
2、四种基础布局
1、线性布局
该布局通过 双标签 实现 、
其属性最为重要 他决定了其布局的方向
1、参数一:horizontal x轴方向水平布局
2、参数二:vertical y轴方向垂直布局
如果 布局方向x轴horizontal水平方向布局
则可以使用权重布局
代码如下
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="100dp">
<Button
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_width="0px"
android:layout_height="20dp"
android:layout_weight="1"/>
<Button
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_width="0px"
android:layout_height="20dp"
android:layout_weight="1"/>
</LinearLayout>
可以使用 gravity 属性设置子元素的排列方式
2、相对布局
3、帧布局
4、百分比布局
3、自定义控件
1、控件的继承
由此流程图可知我们大多数的控件都是直接或者间接继承自view 控件
2、引入布局
我们在这里以重写标题栏为例
大多数时候我们都不需要系统自带的标题栏 或者想着自己定义标题栏
因此我们首先 将系统标题栏隐藏
我们打开需要去除标题栏的活动在活动中重写的OnCreate方法下添加如下代码
// 首先对标题栏的的类进行实例化
ActionBar actionbar=getSupporActionBar();
if(actionbar!=null){
actionbar.hide();
}
然后我们在layout包下重新创建一个名为Titile.xml 的布局
将标题布局设置在 Title.xml 中
然后我们回到 FirstActivity.xml 布局文件中通过 include 标签进行 样式引用 即可 代码如下
<include layout="@layout/title"/>
3、创建自定义控件
我们已经成功引用了 样式布局 但是我们还需要对布局中的按钮 定义响应事件
我们新建一个名为 TitleLayout 的class 然后使其继承于LinearLayout
然后重写Linear Layout 中带有两个函数的的构造函数
public TitleLayout(Context context, AttributeSet attributeSet) {
super(context,attributeSet);
LayoutInflater.from(context).inflate(R.layout.title,this);
Button btn_back=findViewById(R.id.Title_Back);
Button btn_edit=findViewById(R.id.TItle_Edit);
btn_back.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Toast.makeText(getContext(),
"您销毁了 当前控件",
Toast.LENGTH_SHORT).show();
((Activity)getContext()).finish();
}
});
btn_edit.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Toast.makeText(getContext(),
"您点击了 Edit Button",
Toast.LENGTH_SHORT).show();
}
});
}
然后我们通过LayoutInflater中的form方法构建一个LayoutInflater对象 ,然后再用inflate()方法接收两个参数一个是以用布局的id 我们使用R.layout.title,第二个参数这是布局的父布局 我们传入this
然后再向其定义点击事件
然后再重新进行引用即可
代码如下
<com.example.listviewtest.Title
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
4、ListView 控件的使用
1、简单使用
新建项目 ListViewTest
然后创建一个简单的ListView 的布局
返回 MainActivity中编写逻辑代码
首先:通过findViewid 获取到listview
其次构造ArrayAdapter泛型适配器
注意所有的数据都不能直接传给ListVIew
必须通过 适配器才可以执行
代码如下
// 定义数据类容
String arr[]={"张三","李四","王五"}
// 获取控件
ListView listview=findViewId(R.id.ListView_id);
//构造泛型适配器
ArrayAdapter<String>adapter=new ArrayAdapter(
this,
android.R.layout.simple_list_item_1,
arr
);
android.R.layout.simple_list_item_1 指的是Android 中的内置布局文件 用于简单的显示一行数据
2、定制ListViwe 的界面
准备好一组图片
然后生成一个 Fruit 的实体类
撰写成员变量 String name 和 Image Pictrue
撰写构造函数 与 get 函数
代码如下
public class Fruit {
private String name;
private int pictrue;
public Fruit(String name, int pictrue){
this.name=name;
this.pictrue=pictrue;
}
public String getName() {
return name;
}
public int getPictrue() {
return pictrue;
}
}
然后再新建布局fruit_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
<Button
android:id="@+id/title_back"
android:background="@drawable/ic_baseline_arrow_back_ios_24"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/title_text"
android:textSize="20dp"
android:gravity="center"
android:text="Hello Word!"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="6"/>
<Button
android:id="@+id/title_Edit"
android:background="@drawable/ic_baseline_brush_24"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"/>
</LinearLayout>
然后再定义一个实体类 继承自 ArrayAdapter 从而重写适配器
我们将适配器中的List 数据内容指定成 Fruit
并且重写 其中的构造函数 从而拿到 子布局的Id
在重写通过滑动获取数据的方法 getView();
public class Fruit_Adapter extends ArrayAdapter<Fruit> {
private int TextViewResourceId;
public Fruit_Adapter(@NonNull Context context, int resource, @NonNull List<Fruit> objects) {
super(context, resource, objects);
TextViewResourceId=resource;
}
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Fruit fruit= (Fruit) getItem(position); //获取实例
View view= LayoutInflater.from(getContext()).inflate(TextViewResourceId,parent,false);
ImageView imageView=(ImageView) view.findViewById(R.id.fruit_image);
TextView textView=(TextView) view.findViewById(R.id.fruit_name);
imageView.setImageResource(fruit.getPictrue());
textView.setText(fruit.getName());
return view;
}
}
完成之后 我们再将该适配器传入主函数之中即可
public class TowAcitvit extends AppCompatActivity {
private List<Fruit>fruits=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tow_acitvit);
ActionBar actionBar=getSupportActionBar();
actionBar.hide();
// 撰写适配器
ListView listView=findViewById(R.id.Tow_ListView);
initFruit(); // 加载图片数据
Fruit_Adapter adapter=new Fruit_Adapter(TowAcitvit.this,R.layout.fruit_item,fruits);
listView.setAdapter(adapter);
}
private void initFruit(){
for (int i=0; i<=3;i++){
Fruit ren1=new Fruit("张三",R.drawable.to_1);
fruits.add(ren1); // 将撰写好的数据添加到fruits之中
Fruit ren2=new Fruit("李四",R.drawable.to2);
fruits.add(ren2);
Fruit ren3=new Fruit("王五",R.drawable.to3);
fruits.add(ren3);
Fruit ren4=new Fruit("老六",R.drawable.to4);
fruits.add(ren4);
}
}
}
总结
自定义ListView其实非常简单
整体分成四个步骤
1、定义List的布局
每一条数据加载出来都会使用该布局
2、定义 Fruit 类
这个内容用于在滚动时取出相应数据
然后存储每条数据类容 ,有多少条单独类容就有多少条成员变量
3、重新ArrayAdapter类
重新定义一个 实体类 继承自ArrayList 即可
然后重写两条函数即可
第一个构造函数 用于取出将第一条数据的布局id
第二个加载数据的方法 getView 该方法用于将数据加载出来
4、传递适配器
将适配器传入主函数中
使用setAdapter 进行适配器的修改
3、提升ListView运行效率
提升一 : 布局提升
在getView()方法中有一个 convertView 参数 这个参数用于将之前加载的布局进行缓存
代码如下
// 重写的getView()方法中
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view;
if(convertview==null){
view=LayoutInflater.from(getContext()).inflater(resourceID,parent,false)
}else{
view=convertView;
}
// 添加以上代码即可
}
在上面的代码中进行了一次判断 如果 ConvertView 为空 则会使用LayoutInflater进行布局
而如果 ConvertView中存在内容则会直接执行ConvertView中的布局
提升二 : 内容提升
在getView方法中 我们还会重复执行获取 控件按钮的步骤
我们通过 创建;内部类需要的控件填入再从外部获取一次 即可
获取之后只需要在从viewHolder中获取即可
注意获取到控件的id内容之后 需要使用 view 的setTag()方法将 viewHolder 存储起来
再之后在通过 getTag()方法将 viewHolder 取出来即可
代码如下:
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view;
ViewHolder viewholder;
if(convertview==null){
view=LayoutInflater.from(getContext()).inflater(resourceID,parent,false);
// 实例化 View Holder
viewholder=new ViewHolder();
viewholder.imageviwe=findViewId(R.id.imageviewID);
viewholder.textview=findViewID(R.id.textview);
view.setTag(viewHolder);
}else{
view=convertView;
viewHolder.getTag(viweHolder);
}
viewHolder.imageView.setImageResource(fruit.getPictrue());
viewHolder.textView.setText(fruit.getName());
// 添加以上代码即可
}
class ViewHolder(){
ImageView imageview;
TextView textview;
}
4、ListVIew的点击事件
点击事件我们通过主函数实现
原理非常简单 通过注册监视器 如果监视器被触发会自动获取当前被触发的listView id
代码如下
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(TowAcitvit.this,fruits.get(i).getName(),Toast.LENGTH_SHORT)
.show()
}
});
5、RecyclerVIew控件
Recyclerview控件提供了横向滑动并且优化了LIstView 中很多不足的地方
1、RecyClerView 控件的基本用法
首先新建项目RecyclerText
在layout中的Activit_main 中添加Recycler布局
代码如下
<LinearLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
注意:因为版本的不一样可能导致 Recycler view的引用不一样 版本过低的话需要对Recycler控件进行导入依赖包,我们的版本比较新,因此省略了这一步
我们向使用Recycleview 来实现listVIew 同样的效果首先准备一部分图片
然后还需要重新布局和重写Fruit 类
然后再定义一个实体类 FruitAdapter
在再其中 定义一个内部类 名为 ViewHolder 该类继承自RecyclerViwe.viewHolder
然后 该类的ViewHolder构造函数类需要传入一个 View参数;该参数通常就是 RecyClerView子项的最外层布局 然后我们便可以通过 findVIewById 获取到布局中的id
再定义一个全局变量的List 用于存储传入适配器中的数据 外面的数据,在Fruit Adapter 中也存在一个 构造函数 进行赋值的操作便在这里进行
由于FruitAdapter继承自RecyClerHolder因此外面需要重写三个类
1、onCreateVIewHolder()
2、onBIndViewHolder()
3、getItemCount()
第一个方法中将 Fruit_item 布局加载进来然后创建一个ViewHolder 实例
并将加载出来的布局传入到构造函数当中最后返回ViewHolder实例
第二个方法用于对RecyclerView直线的数据进行赋值 每个子项的内容都会在这里进行执行
我们通过得到的Position 参数得到当前项的Fruit 实例
再将对应数据设置到VierHolder 中的需要的数据中即可
第三方法只需返回RecycleView 一共有多少子项即可
代码如下
public class MainActivity extends RecyclerView.Adapter<FruitAdapter.ViewHolder>{
// 内置类
static class ViewHolder extends RecyclerView.ViewHolder{
TextView name;
TextView learnid;
TextView classid;
TextView phone;
ImageView image;
// 该方法用于 获取需要的参数的 id
public ViewHolder(@NonNull View itemView) {
super(itemView);
name=itemView.findViewById(R.id.Name);
learnid=itemView.findViewById(R.id.LearnID);
classid=itemView.findViewById(R.id.ClassID);
phone=itemView.findViewById(R.id.Phone);
image=itemView.findViewById(R.id.ImageID);
}
}
// 重写RecyclerView 中的三个传参方法
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit,parent,false);
ViewHolder holder=new ViewHolder(view);
return holder;
}
// 该方法用于赋值
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// 通过 position 获取当前list 中的参数
Fruit fruit= (Fruit) fruitList.get(position);
holder.learnid.setText(fruit.getLearnid());
holder.classid.setText(fruit.getClassid());
holder.phone.setText(fruit.getPhone());
holder.name.setText(fruit.getName());
holder.image.setImageResource(fruit.getImageid());
}
@Override
public int getItemCount() {
return fruitlist.size();
}
}
执行完毕之后定MainActicity中的值即可
首先我们依旧定义一个intfruit 的方法用于加载 我们需要的数据
然后我们通过 findViewByID 获取到RecyClerView 的 id
然后我们 再实例化 LinearLayoutManager这个对象
意思是当前这个RecyClerView的布局为线性布局
然后再这个对象通过.setLayoutManager传递给RecyclerView
然后再将fruitHolder实例化再将我们加载好数据的List 传入即可
然后整体都定义完成之后
再修改RecyclerView 的适配器内容
代码如下
private List<Fruit>fruits=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intFruit();
// 获取 RecyClerView
RecyclerView recyclerView=findViewById(R.id.main_RecycleyView);
// 定义当前RecyClerView 布局为线性布局
LinearLayoutManager layout=new LinearLayoutManager(this);
recyclerView.setLayoutManager(layout);
FruitHolder fruitHolder=new FruitHolder(fruits);
recyclerView.setAdapter(fruitHolder);
}
public void intFruit() {
Fruit ren1 = new Fruit("张山", "五年级一班", "001", "11122223333", R.drawable.to_1);
fruits.add(ren1);
Fruit ren2 = new Fruit("吴彦祖", "五年级一班", "002", "12312312333", R.drawable.to_1);
fruits.add(ren2);
Fruit ren3 = new Fruit("张三", "五年级一班", "003", "12244423333", R.drawable.to_1);
fruits.add(ren3);
Fruit ren4 = new Fruit("王五", "五年级一班", "004", "11122223333", R.drawable.to_1);
fruits.add(ren4);
Fruit ren5 = new Fruit("六七", "五年级一班", "005", "11122225555", R.drawable.to_1);
fruits.add(ren5);
Fruit ren6 = new Fruit("李四", "五年级一班", "006", "22414124124", R.drawable.to_1);
fruits.add(ren6);
Fruit ren7 = new Fruit("李四", "五年级一班", "007", "22414124124", R.drawable.to_1);L
fruits.add(ren7);
}
}
如果我们需要将RecyclerView中的布局改变成横向的滑动
只需要修改好整体布局之后
然后在LinearLayoutManager实例化对象之后修改其中setOrientation的数据即可 代码如下
LinearLayoutManager layout=new LinearLayoutManager(this);
layout.setOrientation(LinearLayoutManager.HORIZONTAL);
修改成为瀑布流布局 只需要实例化StaggeredGridLayoutManager对象即可该对象需要传入两个个参数
参数一 :瀑布流的列数
参数二 :瀑布流的排版布局
完成之后传递给RecyclerViwe 即可
代码如下
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
into();
RecyclerView recyclerView=findViewById(R.id.main_re);
StaggeredGridLayoutManager layout=new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layout);
FruitAdapter fruitAdapter=new FruitAdapter(fruitList);
recyclerView.setAdapter(fruitAdapter);
//
}
2、RecyclerView 点击事件
在RecyclerView 中并没有像listVIew一样提供OnClickListener的点击方法;需要我们一个一个去注册
但是 有点在于可以指定要点击的地方 不像ListVIew无法指定
我们返回 FruitAdapt中
首先在内部类ViewHolder中注册一个 View fruitView;
再去内部类ViewHolder中的构造方法中进行赋值fruitView=itemView;
这样就保存了整体布局 方便到时候可以点击全体
然后我们在前往onCreateViewHolder方法中进行事件的点击注册即可
然后通过getAdapterPosition即可获取当前用户所选择的 子控件
代码如下
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
private List<Fruit>fruitList;
public FruitAdapter(List<Fruit>fruitList){
this.fruitList=fruitList;
}
static class ViewHolder extends RecyclerView.ViewHolder{
View fruitView;
TextView name;
TextView learnid;
TextView classid;
TextView phone;
ImageView image;
public ViewHolder(@NonNull View itemView) {
super(itemView);
fruitView=itemView;
name=itemView.findViewById(R.id.Name);
learnid=itemView.findViewById(R.id.LearnID);
classid=itemView.findViewById(R.id.ClassID);
phone=itemView.findViewById(R.id.Phone);
image=itemView.findViewById(R.id.ImageID);
}
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit,parent,false);
ViewHolder holder=new ViewHolder(view);
holder.fruitView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position=holder.getAdapterPosition();
Toast.makeText(parent.getContext(),"您选择了学号为"+fruitList.get(position).getLearnid()+"的同学",Toast.LENGTH_SHORT).show();
}
});
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Fruit fruit= (Fruit) fruitList.get(position);
holder.learnid.setText(fruit.getLearnid());
holder.classid.setText(fruit.getClassid());
holder.phone.setText(fruit.getPhone());
holder.name.setText(fruit.getName());
holder.image.setImageResource(fruit.getImageid());
}
@Override
public int getItemCount() {
return fruitList.size();
}
}