AndroidUI控件,布局

版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎留言。 https://blog.csdn.net/qq_15046309/article/details/82927254

 

《第一行代码》第三章内容的整理。

第三章主要是控件的开发,布局的理解,是安卓的基础部分。

 

目录

注册监听器

4种基本布局:

创建自定义控件

ListView控件(已被RecyclerView取代)

RecyclerView


注册监听器

一种是声明为内部类,但是Java规定,内部类只能访问外部类中的成员变量,不能访问外部方法中的变量。解决方法是将方法中的变量声明为final全局变量。但是内部类虽然可以达到效果但是看起来界面不好看。

另一种是实现接口的方式来注册,让此类实现View.OnClickListener接口,然后在类中重写OnClick方法。

  • 变量的声明:

在类中

private Button button;

private EditText edit;

在onCreate方法中

  button=(Button) findViewById(R.id.button);

  edit=(EditText) findViewById(R.id.edit_text);

点击事件

switch (v.getId())
{
    case R.id.button:
        String data=edit.getText().toString();
       Toast.makeText(this,data,Toast.LENGTH_SHORT).show();
        break;
        default:
            break;
}

 

  • Android的ID都是数值,因此可以用数组存储。

4种基本布局:

布局是一种可以放置很多控件的容器,它可以按照一定的规律调整内部控件的位置,从而可以编写出精美的页面。布局还可以放置布局,形成布局的嵌套。

线性布局 LinearLayout

以下两个属性不可缺少

  • android:layout_width

 

  • android:layout_height
使用了android:layout_weight之后,在
android:orientation="vertical"中,android:layout_height就不再管用了。
android:orientation="horizontal中,android:layout_width就不再管用了。
  • 只有线性布局支持layout_weight。指定成0dp是一种规范的写法。dp是Android中用来指定空间大小,间距等属性的单位。
  • Button的大小一般都声明为wrap_content这样有更好的适配特性。

相对布局RelativeLayout,它可以通过相对定位的方式让控件出现在布局的任何位置,该布局虽然繁琐,但都是有规律可循的。

帧布局FrameLayout

这种布局没有方便的定位方式,所有的空间都会默认摆放到布局的左上角,由于定位方式的欠缺(与LinearLayout的layout_gravity相同),所以它的应用场景比较少。

百分比布局

由于LinearLayout本身已经支持按比例指定控件的大小了,因此百分比布局职位FrameLayout和RelativeLayout进行了功能拓展。提供了PercentFrameLayout和PercentRelativeLayout这两个全新的布局。

      百分比布局是新增布局,需要在build.gradle中添加百分比布局库的依赖。

      添加依赖的时候代码是

implementation 'com.android.support:percent:28.0.0'

书上的代码已经过时了,另外这个28.0.0应该和    implementation 'com.android.support:appcompat-v7:28.0.0'的号码一致。(因为电脑问题,未实现)

创建自定义控件

      我们所用的所有的控件都是直接或者间接继承自view的,所用的所有布局直接或间接继承自ViewGroup的。

自定义的控件,也就是layout的文件,写完了之后可以被到处应用。比如在主界面,那么主界面就可以用

<include layout="@layout/name"/>引用完成。

另外一种添加的方法是新建一个类继承LinearLayout,随后在这个类中调用父类构造函数,参数分别是Context和Attribute类型的,随后需要对这个类进行动态加载,

LayoutInflater.from(context).inflate(R.layout.文件名,this);

【动态加载借助LayoutInflater来实现,通过调用其from方法(参数为context)可以构建出一个LayoutInflater的对象,然后在调用inflate方法就可以动态加载布局了,它有多个参数,一是要加载的文件的id,二是给加载好的布局再添加的一个父布局】,有时候会有第三个参数,例如后面讲的ListVIew和RecyclerView

随后便可以在这个类中为控件编写事件了。

 

ListView控件(已被RecyclerView取代)

声明控件首先正常声明,不过在表示的时候,需要在Activity中声明数组来储存一项一项的数据(把数据提供好),数组中的数据是无法直接传给ListView的,安卓提供了许多适配器实现类,最好用的是ArrayAdapter,泛型需要你指定要传的是什么数据类型。它的构造函数

  • Context
  • android.R.layout.simple_list_item_1
  • 数组名

其中android.R.layout.simple_list_item_1作为ListView的子项布局id,这是一个Android内置的布局文件,里面只有一个TextView,可以简单地显示一段文本。

最后实例化ListView,对象调用setAdapter(adapter);

 

      定制ListView文件

这是本章的难点和终点,是Android的重中之重!必须牢牢掌握。现在官方不推荐ListView了,转而推荐RecycleView。

      首先ListView在布局文件中的声明是很简单的,注意使它的

        android:layout_width="match_parent"

        android:layout_height="match_parent”均为match_parent就可以,这样ListView便可以充满整个屏幕。

两种方法使用ListView

  • 仅仅展示文字

声明一个String类型的数组,这里要引入适配器的概念

适配器是一个连接数据和视图的桥梁,适配器就像显示器,把复杂的东西按人可以接受的方式来展现。

不懂没有关系,因为声明是死的。ArrayAdapter是泛型结构。

ArrayAdapter<String> adapter=new ArrayAdapter<String>(context,android.R.layout.simple_list_item1,字符串数组);

其中android.R.layout.simple_list_item1是系统提供的内置布局。我们待会自定义的时候会把它改成我们所需要的。

实例化ListView,最后通过ListView的setAdapter()方法绑定ArrayAdapter。(listview.setAdapter(adapter);)

  • 定制ListView页面

这一节就开始有难度了,对ListView进行定制,展示更丰富的内容,例如图片+文字。(跳过)

RecyclerView

RecyclerView比ListView更加的强大,Android推荐使用这项技术。

  • 引入

Android希望更多的设备都可以用上,所以讲RecyclerView定义在了build.gradle中,打开app目录下的build.gradle,在dependciew闭包中添加

   implementation 'com.android.support:recyclerview-v7:28.0.0'

随后同步更新build.gradle(需要联网)

  • 声明

在布局中加入(所有通过build.grade添加的功能据需如此声明)

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycle_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
  •    步骤

①首先声明一个普通类,这个类包含着文字和图片,接收器等等。

package com.example.recyclerview;

import android.widget.FrameLayout;

public class Fruit {
    private String ImageName;
    private int ImageId;
    public Fruit(String Imagename,int ImageId)
    {
        this.ImageId=ImageId;
        this.ImageName=Imagename;
    }
    public String getImageName()
    {
        return ImageName;
    }
    public  int getImageId()
    {
        return ImageId;
    }
}

②为RecyclerView准备一个适配器

package com.example.recyclerview;

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

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

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
    private List<Fruit> data;

    static class ViewHolder extends RecyclerView.ViewHolder
    {
        View fruitView;
        ImageView imageView;
        TextView textView;
        public ViewHolder(View view)
        {
            super(view);
            fruitView=view;
            imageView=(ImageView) view.findViewById(R.id.image);
            textView=(TextView) view.findViewById(R.id.text);
        }
    }
    public FruitAdapter(List<Fruit> list)
    {
        data=list;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
        View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_list,parent,false);
        final ViewHolder holder=new ViewHolder(view);
        holder.fruitView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position=holder.getAdapterPosition();
                Fruit fruit=data.get(position);
                Toast.makeText(v.getContext()," 点击了"+fruit.getImageName(),Toast.LENGTH_SHORT).show();
            }
        });
       holder.imageView.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               int position=holder.getAdapterPosition();
               Fruit fruit=data.get(position);
               Toast.makeText(v.getContext()," 点击了图片"+fruit.getImageName(),Toast.LENGTH_SHORT).show();

           }
       });
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
        Fruit fruit=data.get(i);
        viewHolder.imageView.setImageResource(fruit.getImageId());
        viewHolder.textView.setText(fruit.getImageName());
    }

    @Override
    public int getItemCount() {
        return data.size();
    }
}


该类继承自RecyclerView.Adapter,泛型为FruitAdapter.ViewHolder,其中ViewHolder为我们声明的一个静态内部类,继承自RecyclerView.ViewHolder。另外需重写以下三种方法

onCreateViewHolder,
onBindViewHolder
getItemCount

先看静态内部类在这个类中首先先声明ImageView和TextView对象,并声明一个View fruitView为点击事件做铺垫。它的构造函数的参数为View类型的,构造函数必须首先super(view),随后实例化刚才声明的两个对象并把参数view传给fruitView。

内部类结束后,需要忙活主类的构造函数,他的参数是一个List类型为我们刚声明的类。把参数传给主类的私有List。

接下来重写三种方法,最简单的是重写getItemCount方法,只要返回私有List的size即可。

重些onCreatViewHolder方法:这个类的意思是要创建视图。用于创建VIewHolder实例,我们把子项的布局加载进来,

 View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_list,parent,false);

并把加载后的布局传到构造函数中,

final ViewHolder holder=new ViewHolder(view);

随后就可以返回holder了,但是为了点击事件,还需要接着做。

当我们点击图片的时候,我们希望他能给我们一个交互,这个图片在holder中,所以我们为ImageView的对象添加监听事件。

  holder.fruitView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position=holder.getAdapterPosition();
                Fruit fruit=data.get(position);
                Toast.makeText(v.getContext()," 点击了"+fruit.getImageName(),Toast.LENGTH_SHORT).show();
            }
        });

敲到new View.OnClickListener时,AS会自动补齐,接下来在监听事件里写就可以了。怎么确认点击的是哪个选项呢?利用VIewHolder的getAdapterPosition拿到用户点击的position(这个子项的position是死的,跟List里的位置一一对应),然后通过position拿到相应的Fruit的实例。

重写onBindViewHolder这个方法是用来对RecyclerView子项的数据进行赋值,会在子项滚动到屏幕内的时候执行,它的参数一个是VIewHolder,一个是position。我们用position可以拿到Fruit的实例,随后将数据设置到ViewHolder中的ImageView和TextView中即可。

③在MainActivity中实现。

首先实例化RecyclerView自不必说,然后传给适配器相应的List文件,并且用RecyclerView的实例去

recyclerView.setAdapter(adapter);

RecyclerView的好处是可以随便更改滑动的样式,所以需要LayoutManager来制定RecyclerView的布局方式。线性布局声明如下

LinearLayoutManager layoutManager=new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);

瀑布方式声明如下

      StaggeredGridLayoutManager layoutManager=new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);//3代表3列
      recyclerView.setLayoutManager(layoutManager);

猜你喜欢

转载自blog.csdn.net/qq_15046309/article/details/82927254