Android第一行代码 Day03 笔记

3.UI开发

常用属性:

  • fill_parent/match_parent:让当前控件的大小和父布局的大小一样
  • wrap_parent:让当前控件的大小刚好能够包含住里面的内容
  • android:background 用于为布局或控件指定一个背景
  • android:layout_margin 指定控件上下左右的偏移的距离

3.1 常用控件

为每一个组件在定义时都制定id,width,height

  • gravity: 对齐方式
  • visibility: visible(控件可见) invisible(控件不可见,但仍占据位置) gone(不可见且不占空间)

3.1.1 TextView文本框

定义:

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="">
    </TextView>

简单使用示例:

  TextView textView = (TextView)findViewById(R.id.textView);
  textView.setText(""); //给textVIew设置值
  textView.getText();//获取textView的值

注意:在为显示聊天信息的文本框设置背景时,需要使用9-Patch图片,这样可以实现自动拉伸。

3.1.2 Button按钮

  • 系统会对button中所有的英文字母自动进行大写转换可以使用textAllCaps属性禁用

  • 只有一个按钮点击事件推荐使用匿名内部类

  • 多个按钮使用点击事件实现View.OnClickListener接口并重写Onclick方法,然后使用switch进行分流

  • 两种为按钮添加点击事件的方法:

    • 一种是在代码中直接绑定
    • 一种是在Activity中编写包含View类型的参数的方法,并通过布局文件android:onClick属性指定方法名

定义:

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text=""
        android:textAllCaps="false">
    </Button>

简单使用:

 Button btn = (Button)findViewById(R.id.button);
 //为按钮设置监听事件  单按钮
 btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this, "你点击了这个按钮", Toast.LENGTH_SHORT).show();
        }
    });
//-----------------------------------------------------------------------------------------

//多个按钮设置点击事件
//方法1:创建  View.OnClickListener实例
 View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           switch (v.getId()){
               //使用switch进行分流
               case R.id.btn:
                   break;
               default:
                   break;
           }
        }
    };
//为按钮设置点击事件
 btn.setOnClickListener(listener);

//-----------------------------------------------------------------------------------------

//方法2:重写onClick()方法
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn:
                break;
            default:
                break;
        }
    }

//为按钮设置点击事件
 btn.setOnClickListener(this)
//-----------------------------------------------------------------------------------------

//通过自定义点击事件函数,通过xml文件绑定
public void myOnClick(View v){
     //编写要执行的代码
}
android:onClick="myOnClick"

3.1.3 EditText编辑框

  • hint: 指定一段提示文本
  • maxLines: 指定editText的最大行数
  • inputType: 控制输入的显示类型

定义:

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint=""
        android:maxLines="1">
    </EditText>

简单使用:

 EditText editText = (EditText)findViewById(R.id.editText);
 //获取输入框中的内容
 editText.getText().toString()

3.1.4 ImageView

用于在屏幕中显示任何Drawable对象,通常用来显示图片。

说明:使用ImageView组件显示图像时,通常需要将要显示的图片放在res/drawable或res/mipmap目录中

  • src: 图片路径
    动态更改ImageView中的图片 使用 setImageResource()方法修改显示的图片路径

定义:

    <ImageView
        android:id="@+id/imgView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/img">
    </ImageView>

简单使用:

ImageView imageView = (ImageView)findViewById(R.id.imgView);
//动态更改ImageView中的图片
imageView.setImageResource(R.drawable.img2);

3.1.5 ProgressBar进度条

显示一个正在加载数据的进度条,不指定visibility属性控件都可见

  • style: 指定进度条的样式
  • max: 指定进度条的最大值
  • getVisibility(): 获取组价可见性
  • setVisibility(): 设置组件的可见性
    可见性:VISIBLE可见 GONE不可见不占位置 INVISIBLE不可见仍占据大小

常用方法:

  • setProgress(int progress):用于设置进度完成的百分比
  • incrementProgressBy(int diff):用于设置进度条的进度的增加或减少。当参数值为正数时,表示增加,反之表示减少。

定义:

<!-- style指定进度条样式  圆形进度条和水平进度条-->
    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"
        android:max="100">
    </ProgressBar>

简单使用:

 progressBar = (ProgressBar)findViewById(R.id.progress_bar);
//动态的更新进度条
//因为在子线程中不能进行UI操作,所以使用 runOnUiThread()方法将线程切回到主线程中
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
            	//获取当前进度值
                int progress = progressBar.getProgress();
                while(progress!=100){
					//更新进度
                    progress += 10;
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //将进度重新设置
                    progressBar.setProgress(progress);

                }
            }
        });

3.1.6 AlertDialog对话框

对话框:置顶于所有界面之上,能屏蔽掉其他控件的交互能力,通过点击事件触发一个alert对话框

创建对话框示例:

 //创建对话框
		 AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
                dialog.setTitle("This is Dialog"); //设置对话框标题
                dialog.setMessage("Something important"); //设置对话框的内容
                dialog.setCancelable(false); //可否用返回键关闭

                //设置确定按钮的点击事件
                dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
 
                    }
                });

                //设置取消按钮的点击事件
                dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
    
                    }
                });

                dialog.show(); //显示对话框

3.1.7 ProgressDialog 进度条对话框

置顶于所有界面之上,能屏蔽掉其他控件的交互能力 会显示进度条
简单使用示例:

	ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
    progressDialog.setTitle("");//设置标题
    progressDialog.setMessage(""); //设置提示消息
    progressDialog.setCancelable(true); //设置可否用返回键关闭
    progressDialog.show(); //显示

	// progressDialog.dismiss();    关闭对话框

3.2 4种基本布局

3.2.1 线性布局管理器(LinearLayout)

线性布局管理器是将放入其中的组件按照垂直或水平方向来布局。在垂直线性布局管理器中每一行只能放一个组件,在水平线性布局管理器中,每一列只能放一个组件。线性布局管理器组件不会换行,当组件排列到窗体的边缘后,剩下的组件将不会被显示。

  • 通过 orientation属性 指定 vertical垂直 horizontal 水平排列(默认)
  • 通过 horizontal 排列时内部控件不能将宽度指定为 match_parent ; 只有垂直方向上的对齐方式才会生效
  • 通过 vertical 排列时不能将高度指定为 match_parent ; 只有水平方向上的对齐方式才会生效

属性:

  • android:gravity: 指定文字在控件中的对齐方式
  • android:layout_gravity: 指定控件在布局中的对齐方式
  • 使用 layout_weight属性时,默认将组件宽度指定为0dp
    指定weight值时,系统将所有控件weight值相加除以总值就是每个控件显示的宽度大小

定义:

<!-- android:orientation:排列方式 -->
<LinearLayout 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"
    android:orientation="horizontal"
    tools:context=".MainActivity">
</LinearLayout>

3.2.2 相对布局管理器(RelativeLayout)

  • alignParent 相对于父布局进行定位
  • 控件相对于控件进行定位 above上方 below 下方 toLeftOf左侧 toRightOf右侧
  • alignLeft:一个控件的左边缘和另一个控件的左边缘对齐
  • alignRight:一个控件的右边缘和另一个控件的右边缘对齐
  • alignTop: 一个控件的上边缘和另一个控件的上边缘对齐
  • alignBottom:一个控件的下边缘和另一个控件的下边缘对齐

定义:

<RelativeLayout 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=".RelativeLayoutActivity">
</RelativeLayout>

3.2.3 帧布局管理器(FrameLayout)

帧布局管理器中每加入一个组件,都将创建一个空白的区域,通常称为一帧,从屏幕的左上角(0,0)坐标点开始布局,多个组件层叠排序,后面的会覆盖前面的组件,即所有的控件都会放在布局左上角。
FrameLayout支持的常用XML属性:

  • android:foreground:设置该帧布局容器的前景图像
  • android:foregroundGravity:定义前景图像显示的位置

定义:

<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=".FrameLayoutActivity">
</FrameLayout>

3.2.4 百分比布局(PercentFrameLayout)

使用前需要在app下的build.gradle文件中引入 implementation ‘androidx.percentlayout:percentlayout:1.0.0’

定义:

<!--	需要多定义一个app的命名空间 -->
		<androidx.percentlayout.widget.PercentFrameLayout 
			xmlns:android="http://schemas.android.com/apk/res/android"
			xmlns:app="http://schemas.android.com/apk/res-auto"
			android:layout_width="match_parent"
			android:layout_height="match_parent"
			xmlns:tools="http://schemas.android.com/tools"
			tools:context=".PercentFrameLayoutActivity">	
		</androidx.percentlayout.widget.PercentFrameLayout>

<!--给每个组件设置宽高时使用 以百分比的形式-->
	 	app:layout_heightPercent=""
     	app:layout_widthPercent=""

3.3 自定义控件

所有控件都是直接或间接继承自View,所有的布局都是直接或间接继承自ViewGroup
ViewGroup: 可以包含很多子View和子ViewGroup,用于放置控件和布局的容器

3.3.1 引入其他布局文件

 <include layout="@layout/布局文件名称"/>

3.3.2 创建自定义控件

  1. 创建一个继承于android.view.View类的View类,并且重写构造方法(自定义的view类中,至少需要重写一个构造方法),在布局文件中引入该控件时就会调用构造函数,在构造函数中需要对标题栏布局进行动态加载
  2. 根据需要重写其他的方法
  3. 在项目的活动中,创建并实例化自定义View类,并将其添加到布局管理器中,或者在布局文件中添加自定义控件

LayoutInflater: 布局服务
加载布局的方法: inflate (int resource(对应的布局资源id), ViewGroup root(为该布局的外部在嵌套一层父布局), boolean attachToRoot(是否为加载的布局添加一个root的外层容器))

动态加载布局示例:

   LayoutInflater.from(context).inflate(R.layout.布局文件,this,false);

在布局文件中添加自定义控件:

<!-- 标签名为自定义控件的全类名-->
    <com.example.全类名
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </com.example.全类名>

3.4 ListView列表

数组中的数据无法直接传递给ListView 需要借助适配器来完成
ListView的简单使用: ArrayAdapter的构造函数参数 当前上下文、ListView子项布局的id、需要适配的数据

ListView子项布局id 详细说明:

  • android.R.layout.simple_list_item_1 一行text
  • android.R.layout.simple_list_item_2 一行title,一行text
  • android.R.layout.simple_list_item_single_choice 单选按钮
  • android.R.layout.simple_list_item_multiple_choice 多选按钮
  • android.R.layout.simple_list_item_checked checkbox 复选框按钮

定制ListView的界面:

  1. 定义一个实体类 作为ListView适配器的适配类型
  2. 自定义一个ListView子项的布局文件
  3. 创建一个自定义的适配器继承自ArrayAdapter,并将泛型指定为实体类的类型
  4. 重写getView()方法(该方法在每个子项被滚动到屏幕内的时候会被调用,每次都会重新加载布局),获取当前项的实体类的实例, 并使用LayoutInflater 加载传入的布局
  5. 获取布局文件中组件的实例,设置组件要显示的内容 并返回 view
  6. 在主活动中将数据初始化,并创建自定义适配器的实例传入上下文对象、布局文件id、数据
  7. 给listView设置适配器

优化ListView的运行效率

  1. 运用convertView将加载好的布局缓存,如果为null,则使用 LayoutInflater加载布局,如果不为null则直接复用
  2. 借助一个内部类将控件的实例进行缓存
    如果 convertView为null,使用LayoutInflater加载布局
    同时创建内部类实例将其中的控件进行获取,然后使用setTag()将内部类加入到view中
    如果 convertView不为null,使用getTag()从view中获取内部类实例
  3. 给内部类中的控件设置要显示的内容

ListView的点击事件:

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
               //position 当前点击的定位
            }
        });

定义:

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </ListView>

简单使用示例(基本固定写法):

//首先创建一个实体类作为适配器的适配类型
//TODO:
//定义子项布局文件
//TODO:


//创建一个Adapter类
public class DemoAdapter extends ArrayAdapter<实体类名> {

    private int resourceId;
    public DemoAdapter(@NonNull Context context, int resource, @NonNull List<实体类名> objects) {
        super(context, resource, objects);
        resourceId = resource;
    }

    class ViewHolder{
        //定义子项布局文件中的控件
    }
    /**
     * 该方法在每个子项被滚动到屏幕内的时候会被调用,每次都会重新加载布局
     * @param position
     * @param convertView 用于将之前加载好的布局进行缓存
     * @param parent
     * @return
     */
    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

        getItem(position); // 通过getItem()方法获取当前项的实例
        View view;
        ViewHolder viewHolder;
        if(convertView == null){
            view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
            viewHolder = new ViewHolder();
            //实例化ViewHolder中定义的控件
			//TODO:
            //将ViewHolder存储在View中
            view.setTag(viewHolder); 
        }else{
            view = convertView;
            viewHolder = (ViewHolder)view.getTag(); //重新获取ViewHolder

        }
		
		//给ViewHolder中的控件设置值
		//TODO:

        return view;
    }
}


//在主活动中
	//初始化list数据
	//TODO:
	//获取adapter实例,并给ListView设置adapter
    DemoAdapter adapter = new DemoAdapter(MainActivity.this,R.layout.布局文件,list);
    ListView listView = (ListView)findViewById(R.id.list_view);
    listView.setAdapter(adapter);

3.5 RecyclerView 滚动控件

使用RecyclerView滚动控件

  1. 在app目录下 build.gradle文件中dependencies中 引入 implementation ‘com.android.support:recyclerview-v7:27.1.1’
    在布局xml文件中 添加 androidx.recyclerview.widget.RecyclerView

  2. 为RecyclerView准备一个适配器继承自RecyclerView.Adapter,定义成员变量 数据源list,并指定泛型为 适配器中的内部类 ViewHolder(需要自定义并继承自RecyclerView.ViewHolder)

  3. ViewHolder类中具体:
    成员变量为要显示的控件
    在构造函数中传入View参数,通常为RecyclerView子项的最外层布局 将控件实例化

  4. Adapter适配器类中的构造函数中将全局数据源list赋值,并重写父类的3个方法

    • onCreateViewHolder(ViewGroup parent, int viewType): 用于创建ViewHolder的实例,并将加载出来的布局传入到构造函数中,返回viewHolder实例
    • onBindViewHolder(ViewHolder holder, int position): 对RecyclerView中的子项进行赋值,根据position从数据源list中获取对象实例进行赋值
    • getItemCount():返回数据源的长度
  5. 在主活动中定义数据源list,将list赋值或者初始化,创建布局管理器对象,线性布局,瀑布流布局,网格布局选其一,然后通过setLayoutManager()方法为RecyclerView设置布局方式,实例化适配器对象,并通过setAdapter()方法设置适配器

布局管理器:

  • LinearLayoutManager 线性布局:
    默认是纵向滚动的 通过setOrientation()方法设置 滚动方式
    • 纵向排列: 布局文件设置水平排列 宽为 match_parent 高度为 wrap_content 让组件垂直居中
    • 横向排列: 布局文件设置为垂直排列 明确设置宽度大小 高度为 wrap_content 让组件水平居中
  • GridLayoutManager 网络布局
    两个参数:第一个参数用于指定上下文,第二个参数指定列数
  • StaggeredGridLayoutManager 瀑布流布局
    宽度根据列数自动适配
    两个参数:第一个参数用于指定布局列数 第二个参数用于指定布局的排列方向

制作9patch图片,在AS中png图片右键

定义:

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </androidx.recyclerview.widget.RecyclerView>

简单使用示例(基本固定写法):

//定义一个实体类
//TODO:

//创建一个适配器类继承自RecyclerView.Adapter

public class DemoAdapter extends RecyclerView.Adapter<DemoAdapter.ViewHolder> {
    private List<实体类名> mlist;

    public DemoAdapter(List<实体类名> mlist) {
        this.mlist = mlist; //赋值
    }

    /**
     * 用于创建ViewHolder实例
     */
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.子项布局文件名,parent,false);
        //将加载出来的布局传入到 ViewHolder 的构造函数
        final ViewHolder holder = new ViewHolder(view);

        /**
         * RecyclerView的点击事件
         * 可以给每个控件分开设置
         */

        //控件的点击事件
        holder.控件名.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
           		 //获取用户点击的position
                int position = holder.getAdapterPosition(); 
                //通过position获取点击项实例
                mlist.get(position); 
            }
        });

        return holder;
    }

    /**
     * 用于对RecyclerView子项数据进行赋值,会在每个子项滚动到屏幕内的时候执行
     */
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        mlist.get(position); //根据position在数据源中获取对应实例
       	//给ViewHolder中的控件赋值
       	//TODO:
    }

    @Override
    public int getItemCount() {
        return mlist.size(); //返回数据源的长度
    }

    static class ViewHolder extends RecyclerView.ViewHolder{
        View view;
        //定义子项布局文件中的控件
		//TODO:

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            view = itemView;
			
			//实例化控件
			//TODO:
        }
    }
}

//在主活动中
  //初始化 数据源list数据
  //TOOD:
  
  RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view); 
  //以下布局使用其一即可
  //使用LinearLayout水平布局
  LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
  recyclerView.setLayoutManager(linearLayoutManager); //指定为线性布局的方式  默认是纵向排列的
  linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
  recyclerView.setLayoutManager(linearLayoutManager);  // 指定为横向布局的方式


  //使用瀑布布局 参数含义为一行3列且垂直排列
  StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
  recyclerView.setLayoutManager(layoutManager);


  //使用网格布局  参数含义为一行4列
   GridLayoutManager layoutManager = new GridLayoutManager(MainActivity.this,4);
   recyclerView.setLayoutManager(layoutManager);
	
  //给recyclerView设置adapter
  DemoAdapter adapter = new DemoAdapter(list);
  recyclerView.setAdapter(adapter);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值