路漫漫其修远兮,吾将上下而求索|

阿寳同學Zybao

园龄:3年10个月粉丝:1关注:5

Android UI控件及布局

Android UI控件及布局

学习目标

1、掌握常用布局的特点和使用方法
2、掌握常用控件的功能和使用方法
3、熟悉自定义控件的实现和使用方法
4、掌握ListView的使用方法
5、掌握Fragment的使用方法

控件

1.TextView 主要用于界面上显示一段文本信息

android:gravity   来指定文字的对齐方式
android:textSize  来指定文字的大小
android:textColor  来指定文字的颜色

2.Button 按键按钮用于点击事件

android:textAllCaps="false" 禁用所有英文大小写转换
setOnClickListener 设置监听

3.EditText 允许用户在控件里输入和编辑内容

EditText editText = findViewById(R.id.edit_text)
editText.getText().toString()
//以上从编辑框中获取输入的内容

4.ImageView 图片展示控件

ImageView imageView = findViewById(R.id.image_view);
imageView.setImageResource(R.drawable.img_2);
//重新设置图片的资源地址

5.ProgressBar 进度条

<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
progressBar.setVisibility(View.VISIBLE) //设置属性可见
progressBar.setVisibility(View.GONE) //设置属性不可见

ProgressBar progressBar = findViewById(R.id.progress_bar);
progressBar.setProgress(progressBar.getProgress() + 10);
//设置进度条的进度+10

6.AlertDialog 当前页面弹出一个对话框

AlertDialog.Builder 创建 AlertDialog的实例 设置内容是否可取消等属性

7.ProgressDialog 进度条对话框

setCancelable()中传入了false的话,表示不能通过Back取消掉,当数据加载完必须调用dismiss()方法关闭对话框

四种基本布局

1.线性布局LinearLayout

android:orientation  可以设置排列的方向(竖直vertical,水平horizontal )
android:layout_weight  允许使用比例方式来指定控件的大小
android:layout_gravity 用于指定控件在布局中的对齐方式

2.相对布局RelativeLayout

android:layout_alignParentLeft
android:layout_alignParentRight
android:layout_alignParentTop
android:layout_centerInParent
android:layout_alignParentBottom

以上的针对布局的左右上中下

android:layout_above="@id/relative_button3"
android:layout_below="@id/relative_button3"
android:layout_toLeftOf="@id/relative_button3"
android:layout_toRightOf="@id/relative_button3"

以上的相对与一个按钮的上下左右布局

3.帧布局FrameLayout

4.百分比布局

百分比布局,属于新增布局,需要增加依赖库

引入布局

1.新建布局文件title.xml(线性布局的LinearLayout)
2.在加载的文件中使用include进行引入子布局
<include layout="@layout/title"/>

创建自定义控件

1.新建java 类继承LinearLayout ,重写构造函数,通过LayoutInflater的from()方法可以构建LayoutInflater对象,调用inflate()方法动态加载一个布局文件

2.布局文件修改

最常/难用的控件--ListView

1.ListView简单用法

在布局的xml中增加<ListView>标签

代码中处理使用ArrayAdapter适配器实现
android.R.layout.simple_list_item_1
是安卓内部布局文件,作为ListView子布局的id

2.定制ListView界面

public class MainActivity5 extends BaseActivity {
    private List<Fruit> fruitList = new ArrayList<>();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mainfive);
        initFruits();
        FruitAdapter adapter = new FruitAdapter(MainActivity5.this, R.layout.fruit_item, fruitList);
        ListView listView = findViewById(R.id.list_view);
        listView.setAdapter(adapter);
    }


    public void initFruits() {
        for (int i = 0; i < 2; i++) {
            Fruit apple = new Fruit("apple", R.drawable.apple);
            fruitList.add(apple);
            Fruit banana = new Fruit("banana", R.drawable.banana);
            fruitList.add(banana);
            Fruit orange = new Fruit("orange", R.drawable.orange);
            fruitList.add(orange);
            Fruit pear = new Fruit("pear", R.drawable.pear);
            fruitList.add(pear);
        }
    }
}

public class FruitAdapter extends ArrayAdapter<Fruit> {
    private int resourceId;

    public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects) {
        super(context, textViewResourceId, objects);
        resourceId = textViewResourceId;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Fruit fruit = getItem(position);
        View view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
        ImageView fruitImage = view.findViewById(R.id.fruit_image);
        TextView fruitName = view.findViewById(R.id.fruit_name);
        fruitImage.setImageResource(fruit.getImageId());
        fruitName.setText(fruit.getName());
        return view;
    }


}

3.优化ListView运行效率

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Fruit fruit = getItem(position);
    View view;
    ViewHolder viewHolder;
    if(convertView == null){
        view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
        viewHolder = new ViewHolder();
        viewHolder.fruitImage = view.findViewById(R.id.fruit_image);
        viewHolder.fruitName = view.findViewById(R.id.fruit_name);
        view.setTag(viewHolder);//将ViewHolder储存在View中
    }else {
        view = convertView;
        viewHolder = (ViewHolder) view.getTag();//重新获取ViewHolder
    }
    viewHolder.fruitImage.setImageResource(fruit.getImageId());
    viewHolder.fruitName.setText(fruit.getName());
    return view;
}


class ViewHolder{
    ImageView fruitImage;
    TextView fruitName;
}

4.ListView点击事件

setOnItemClickListener方法为ListView注册一个监听器
用户点击ListView中任何一个子项会回调onItemClick()
通过position参数判断出用户点击的是哪个子项,获取相应的水果
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainfive);
    initFruits();
    FruitAdapter adapter = new FruitAdapter(MainActivity5.this, R.layout.fruit_item, fruitList);
    ListView listView = findViewById(R.id.list_view);
    listView.setAdapter(adapter);
    listView.setOnItemClickListener((parent, view, position, id) -> {
        Fruit fruit = fruitList.get(position);
        Toast.makeText(MainActivity5.this,fruit.getName(),Toast.LENGTH_SHORT).show();
    });
}

强大的滚动控件---RecyclerView

1.RecyclerView基本用法

app/build.gradle导入依赖

implementation 'androidx.recyclerview:recyclerview:1.2.1'
修改布局文件
<?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">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>
新建适配类继承RecyclerView.Adapter,指定泛型FruitAdapter.ViewHolder
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {

    private List<Fruit> mFruitList;

    public FruitAdapter(List<Fruit> fruitList) {
        mFruitList = fruitList;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }

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

    static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(View view) {
            super(view);
            fruitImage = view.findViewById(R.id.fruit_image);
            fruitName = view.findViewById(R.id.fruit_name);
        }
    }

}

2.入口函数

public class MainActivity extends AppCompatActivity {
    private List<Fruit> fruitList = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_view);
        //初始化数据
        initFruits();
        //获取滚动视图
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //让布局横行排列
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        //设置视图的布局管理
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        //设置视图的适配器
        recyclerView.setAdapter(adapter);
    }

    public void initFruits() {
        for (int i = 0; i < 6; i++) {
            Fruit apple = new Fruit("apple", R.drawable.apple);
            fruitList.add(apple);
            Fruit banana = new Fruit("banana", R.drawable.banana);
            fruitList.add(banana);
            Fruit orange = new Fruit("orange", R.drawable.orange);
            fruitList.add(orange);
            Fruit pear = new Fruit("pear", R.drawable.pear);
            fruitList.add(pear);
        }
    }
}

3.带点击处理的

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {


    private List<Fruit> mFruitList;

    public FruitAdapter(List<Fruit> fruitList) {
        mFruitList = fruitList;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
        ViewHolder holder = new ViewHolder(view);
        holder.fruitView.setOnClickListener(v ->
                Toast.makeText(v.getContext(),"you clicked view "+ mFruitList.get(holder.getBindingAdapterPosition()).getName(),Toast.LENGTH_SHORT).show());
        holder.fruitImage.setOnClickListener(v ->
        Toast.makeText(v.getContext(),"you clicked image "+ mFruitList.get(holder.getBindingAdapterPosition()).getName(),Toast.LENGTH_SHORT).show());
        return holder;
    }


    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }


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


    static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView fruitImage;
        TextView fruitName;
        View fruitView;
        public ViewHolder(View view) {
            super(view);
            fruitView = view;
            fruitImage = view.findViewById(R.id.fruit_image);
            fruitName = view.findViewById(R.id.fruit_name);
        }
    }


}

编写界面的最佳实践

1.制作.9图片

选择图片,右击选择create 9-path file选项
小黑点进行绘制边缘,shift拖动擦除

1:黑色条位置向下覆盖的区域表示图片横向拉伸时,只拉伸该区域
2:黑色条位置向右覆盖的区域表示图片纵向拉伸时,只拉伸该区域
3:黑色条位置向上覆盖的区域表示图片纵向显示内容的区域(在手机上主要是文字区域)
4:黑色条位置向左覆盖的区域表示图片横向显示内容的区域(在手机上主要是文字区域)

制作完成后,删除之前的message.png,保留message.9.png
<?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:background="@drawable/message">
</LinearLayout>

注意点:xml中名称是不带.9的,还是之前的message

2.编写聊天界面

2.1写主界面的xml

<?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:background="#77F8A9A9"
    android:padding="10dp"
    android:orientation="vertical">


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


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:orientation="horizontal">


        <EditText
            android:id="@+id/input_text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="Type somrthing here"
            android:maxLines="2" />


        <Button
            android:id="@+id/send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Send" />
    </LinearLayout>
</LinearLayout>

2.2写msg_item的xml

<?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">


    <LinearLayout
        android:id="@+id/left_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/message"
        android:layout_gravity="left"
        android:orientation="vertical">


        <TextView
            android:id="@+id/left_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:gravity="center"
            android:textColor="#fff" />
    </LinearLayout>


    <LinearLayout
        android:id="@+id/right_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/message"
        android:layout_gravity="right"
        android:orientation="vertical">
        <TextView
            android:id="@+id/right_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:gravity="center" />
    </LinearLayout>
</LinearLayout>
注意点:这里的左右布局采用的是layout_gravity(布局问题一定注意,影响显示,或者不展示之类的)
android:gravity 是设置该view里面的内容相对于该view的位置, 例如设置button里面的text相对于view的靠左,居中等位置
android:layout_gravity 是用来设置该view相对与父view的位置, 例如设置button在layout里面的相对位置:屏幕居中,水平居中等

2.3新建Msg实体类

package com.example.uibestpractice;

public class Msg {
    public static final int RECIVED_TYPE = 0;
    public static final int SEND_TYPE = 1;
    private int type;
    private String content;


    public int getType() {
        return type;
    }
    
    public String getContent() {
        return content;
    }


    public Msg(int type, String content) {
        this.type = type;
        this.content = content;
    }
}

2.4新建MsgAdpter

public class MsgAdpter extends RecyclerView.Adapter<MsgAdpter.ViewHolder> {
    private List<Msg> mMsgList;


    public MsgAdpter(List<Msg> msgList) {
        mMsgList = msgList;
    }


    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }


    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Msg msg = mMsgList.get(position);
        if(msg.getType() == Msg.RECIVED_TYPE){
            holder.leftMsg.setText(msg.getContent());
            holder.leftLayout.setVisibility(View.VISIBLE);
            holder.rightLayout.setVisibility(View.GONE);
        }else if(msg.getType() == Msg.SEND_TYPE){
            holder.rightMsg.setText(msg.getContent());
            holder.rightLayout.setVisibility(View.VISIBLE);
            holder.leftLayout.setVisibility(View.GONE);
        }


    }


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


    static class ViewHolder extends RecyclerView.ViewHolder {
        LinearLayout leftLayout;
        LinearLayout rightLayout;
        TextView leftMsg;
        TextView rightMsg;


        public ViewHolder(View view) {
            super(view);
            leftLayout = view.findViewById(R.id.left_layout);
            rightLayout = view.findViewById(R.id.right_layout);
            leftMsg = view.findViewById(R.id.left_msg);
            rightMsg = view.findViewById(R.id.right_msg);
        }
    }
}

2.5修改入口Activity

public class MainActivity extends AppCompatActivity {
    private List<Msg> mMsgList = new ArrayList<>();
    private MsgAdpter adapter;
    private RecyclerView recyclerView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initMsg();
        adapter = new MsgAdpter(mMsgList);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(adapter);
        findViewById(R.id.send).setOnClickListener(view -> {
            EditText input = findViewById(R.id.input_text);
            if (!"".equals(input.getText().toString())) {
                mMsgList.add(new Msg(Msg.SEND_TYPE, input.getText().toString()));
                adapter.notifyItemInserted(mMsgList.size() - 1);
                recyclerView.scrollToPosition(mMsgList.size() - 1);
                input.setText("");
            }
            if(mMsgList.size() == 3){
                mMsgList.add(new Msg(Msg.RECIVED_TYPE,"What's your name?"));
                adapter.notifyItemInserted(mMsgList.size()-1);
                recyclerView.scrollToPosition(mMsgList.size()-1);
            }
            if(mMsgList.size() == 5){
                mMsgList.add(new Msg(Msg.RECIVED_TYPE,"Nice to meet you,Bye!"));
                adapter.notifyItemInserted(mMsgList.size()-1);
                recyclerView.scrollToPosition(mMsgList.size()-1);
            }
            if(mMsgList.size() == 6){
                mMsgList.add(new Msg(Msg.SEND_TYPE,"Bye"));
                adapter.notifyItemInserted(mMsgList.size()-1);
                recyclerView.scrollToPosition(mMsgList.size()-1);
            }
        });
    }


    private void initMsg() {
        Msg msg1 = new Msg(Msg.RECIVED_TYPE, "你好!");
        mMsgList.add(msg1);
        Msg msg2 = new Msg(Msg.SEND_TYPE, "你好呀!");
        mMsgList.add(msg2);
    }
}

聊天项目

	1. 横向布局管理创建 new LinearLayoutManager(this)
	2. RecyclerView设置布局管理、设置适配器
	3. MsgAdpter适配器继承RecyclerView.Adapter,其中onBindViewHolder函数会根据List大小循环调用绑定
posted @   阿寳同學Zybao  阅读(143)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起