zoukankan      html  css  js  c++  java
  • 《第一行代码》阅读笔记(六)——AndroidUI控件(初级)

    这一部分书中讲的十分简洁,估计是因为作者考虑到大家刚刚接触到Android,所以没有展开。而控件的使用其实也是非常简单的事情,只要有Java的基础,再了解一些控件的属性,就可以得心应手了。所以笔者在这里补充一些控件的使用,也十分简单。如果暂时不能理解,也不要担心,先往下看,等到明白的时候在回过头来,就会发现真的特别简单。

    TextView

    属性

            android:id="@+id/txv1"
    

    当前控件唯一标识符,以后的交互中会经常使用,相当于这个控件的name

            android:layout_width="match_parent"
            android:layout_height="wrap_content"
    

    控件的宽度和高度,每个控件都有,除了可以指定数据还可以使用match_ parent、 fill_ parent和wrap_ content。现在fill_ parent已经不用了。关于match_ parent和wrap_ content书中是这样讲的,我觉得还是挺简单明了的。

    ——第一行代码
    然后使用android:layout_ width 和android: layout_ height 指定了控件的宽度和高度。Android 中所有的控件都具有这两个属性,可选值有3种: match_ parent、 fill_ parent和wrap_ content。 其中match_ parent 和fill_ parent 的意义相同,现在官方更加推荐使用match_ parent。 match_ parent 表示让当前控件的大小和父布局的大小-样,也就是由父布局来决定当前控件的大小。wrap_ content 表示让当前控件的大小能够刚好包含住里面的内容,也就是由控件内容决定当前控件的大小。所以上面的代码就表示让TextView的宽度和父布局一样宽,也就是手机屏幕的宽度,让TextView的高度足够包含住里面的内容就行。当然除了使用上述值,你也可以对控件的宽和高指定一个固定的大小,但是这样做有时会在不同手机屏幕的适配方面出现问题。

    总结起来就是一句话,match_ parent是填充父布局,wrap_ content是自己有多少占多少。

       android:gravity="center"
    

    指定控件中内容的位置,书中是这样介绍的

    ——第一行代码
    我们使用android:gravity来指定文字的对齐方式,可选值有top、bottom. left、right、center等,可以用来同时指定多个值,这里我们指定的center, 效果等同于center_vertical|center_ horizontal, 表示文字在垂直和水平方向都居中对齐。

        android:text="This is a text"
        android:textColor="#00ff00"
        android:textSize="60sp" />
    

    这三个简单明了,分别是文字,文字颜色和文字大小。
    这里附上一个文字颜色表,仅供参考

    Button

    Button按钮的属性基本上和TextView相似,值得注意的是

    1. 可以使用android:textAllCaps="false"来禁止Button中的文字转化成为大写
    2. 可以在Activity里面为按钮绑定监听器事件
    Button btnId = (Button) findViewById(R.id.btn_id);
            btnId.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                   //此处添加逻辑
                }
            });
    

    EditText

    EditText是一个对话框,用处十分广泛,像QQ、短信等等,而控件属性大同小异,而文中提到比较特殊的就是

    1. android:hint=“xxx” 类似于提示,在登录界面时,每个对话框会提示需要输入的是账号或者密码,当输入文字时消失。
    2. android:maxLines=“2”。因为之前设置的宽度是可变的,随着输入内容的不断增加会变得不好看,设置了这个最大行数,就可以在超过两行时自动向下拉取进度条,而不调整控件大小。

    ImageView

    展示图片的控件,通过android:src来指定图片的位置,图片一般存放在drawable中,可以存放不同分辨率的图片,这样在不同设备上都可以显示。

    ProgressBar

    是界面上显示的一个进度条

    为了实现进度条的功能,需要调整控件的可见性。

    ——第一行代码
    Android控件的可见属性。所有的Android控件都具有这个属性,可以通过android:visibility进行指定,可选值有3种: visible、 invisible 和gone。visible 表示控件是可见的,这个值是默认值,不指定android:visibility时,控件都是可见的。invisible 表示控件不可见,但是它仍然占据着原来的位置和大小,可以理解成控件变成透明状态了。gone 则表示控件不仅不可见,而且不再占用任何屏幕空间。我们还可以通过代码来设置控件的可见性,使用的是setVisibility()方法,可以传人View. VISIBLE、View. INVISIBLE和View. GONE这3种值。

    其中有一个属性可以设置进度条的格式,就是Style。

    <ProgressBar
                android:id="@+id/pb_normal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
    
            <ProgressBar
                android:id="@+id/pb_small"
                style="?android:attr/progressBarStyleSmall"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
    
            <ProgressBar
                android:id="@+id/pb_large"
                style="?android:attr/progressBarStyleLarge"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
    
            <ProgressBar
                android:id="@+id/pb_horizontal"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
    
    
            <ProgressBar
                android:id="@+id/pb_horizontal_default"
                style="@android:style/Widget.ProgressBar.Horizontal"
                android:max="100"
                android:progress="50"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
    

    对应

    很简单对不对。其中还可以通过android:max="100",android:progress="50" 来实现进度条的模拟。

    但是这不是一个静止的画面,需要让他动起来。怎么做呢?主要的思路就是,先开一个子线程,在线程中加载耗时操作,并发送信息。然后,通过Handler机制接受信息,更新进度条,完成后隐藏进度条。

    第一步:声明变量

    private ProgressBar progressBar;
        private int mProgress = 0;
        private Handler mHandler;
    
    

    这个不多说,mProgress用来记录进度,默认是零。然后还有一些绑定布局啥的就不说了。

    第二步:开辟一个线程

    new Thread(new Runnable() {
                @Override
                public void run() {               
                }          
            }).start();
    

    这个不解释了吧,实例一个Thread,以匿名内部类的方式传入Runable类,并且重写run方法,然后start()运行run中的内容。

    第三步:写一个耗时方法

      private int doWork() {
                    mProgress += Math.random() * 10;
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return mProgress;
                }
    

    Math.random()就是生成0到1之间的随机小数,这里+=包括一个强转。之后每次睡2s。

    第四步:

    while (true) {
                        mProgress = doWork();
                        Message m = new Message();
                        if (mProgress < 100) {
                            m.what = 0x111;
                            mHandler.sendMessage(m);
                        } else {
                            m.what = 0x110;
                            mHandler.sendMessage(m);
                            break;
                        }
                    }
    

    首先就是把doWork()的进度传给mProgress,全局变量一般带个m。然后实例一个Message用来传递信息,如果mProgress小于100,m.what为一个值。大于100说明任务完成,传另外一个值,然后别忘记break。

    第五步:实例Handler

    mHandler = new Handler() {
                @Override
                public void handleMessage(@NonNull Message msg) {
                    if (msg.what == 0x111) {
                        progressBar.setProgress(mProgress);
                                     } else {
                        Toast.makeText(MainActivity.this, "耗时操作已完成", Toast.LENGTH_SHORT).show();
                        progressBar.setVisibility(View.GONE);
                    }
                }
            };
    

    实例一个Handler,然后重写handleMessage方法。传入的msg就是之前发送的msg,然后判断一下,更改progress的值,或者完成,隐藏控件。

    好了,运行测试,就可以体验动态进度条了。下面附上一个完整的文件,结构更清晰。

    public class MainActivity extends AppCompatActivity {
        private ProgressBar progressBar;
        private int mProgress = 0;
        private Handler mHandler;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            progressBar = findViewById(R.id.p);
    
            mHandler = new Handler() {
                @Override
                public void handleMessage(@NonNull Message msg) {
                    if (msg.what == 0x111) {
                        progressBar.setProgress(mProgress);
                                     } else {
                        Toast.makeText(MainActivity.this, "耗时操作已完成", Toast.LENGTH_SHORT).show();
                        progressBar.setVisibility(View.GONE);
                    }
                }
            };
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        mProgress = doWork();
                        Log.i("TAG", "handleMessage: " + mProgress);
                        Message m = new Message();
                        if (mProgress < 100) {
                            m.what = 0x111;
                            mHandler.sendMessage(m);
                        } else {
                            m.what = 0x110;
                            mHandler.sendMessage(m);
                            break;
                        }
                    }
                }
    
                private int doWork() {
                    mProgress += Math.random() * 10;
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return mProgress;
                }
            }).start();
        }
    
    }
    
    

    还有一种Handler传递方式,我觉得更加符合咱们思维。是通过sendEmptyMessage直接传递Message.what,省去了实例化Message的步骤。而接收的时候使用Switch判断。附上实例

    public class MainActivity extends AppCompatActivity {
        ……
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
              ……
    
            mHandler = new Handler() {
                @Override
                public void handleMessage(@NonNull Message msg) {
                    switch (msg.what) {
                        case 100:
                            progressBar.setProgress(mProgress);
                            break;
                        case 200:
                            Toast.makeText(MainActivity.this, "耗时操作已完成", Toast.LENGTH_SHORT).show();
                            progressBar.setVisibility(View.GONE);
                            break;
                        default:
                            break;
                    }
                }
            };
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        mProgress = doWork();
                        if (mProgress < 100) {
                            mHandler.sendEmptyMessage(100);
                        } else {
                            m.what = 0x110;
                            mHandler.sendEmptyMessage(200);
                            break;
                        }
                    }
                }
    
                private int doWork() {
                     ……
                }
            }).start();
        }
    
    }
    
    

    AlertDialog

    AlertDialog是一个对话框,在所有控件之上,可以屏蔽其他控件的交互能力。也非常简单。

    先展示几个效果

    1. 普通提示对话框

    //双选对话框
                    AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();
                    alertDialog.setIcon(R.mipmap.ic_launcher);
                    alertDialog.setTitle("乔布斯");
                    alertDialog.setMessage("活着就是为了改变世界,难道还有还有其他原因吗?");
                    alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "是", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(MainActivity.this, "您单击了是按钮", Toast.LENGTH_SHORT).show();
                        }
                    });
                    alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "否", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(MainActivity.this, "您单击了否按钮", Toast.LENGTH_SHORT).show();
                        }
                    });
                    alertDialog.show();
    

    具体介绍一下用到的方法吧:

    • setTitle:设置对话框的标题,比如“提示”、“警告”等;
    • setMessage:设置对话框要传达的具体信息;
    • setIcon: 设置对话框的图标;
    • setCancelable: 点击对话框以外的区域是否让对话框消失,默认为true;
    • setOnShowListener:对话框显示时触发的事件;
    • setOnCancelListener:对话框消失时触发的事件。
    • setButton:传递了三个参数,第一个就是按钮的类型,BUTTON_NEUTRAL、BUTTON_NEGATIVE和BUTTON_POSITIVE,分别对应的就是图中的对的选择和错的选项。还有个中立选项,位置在弹出的对话框的最左边。第二个参数就是按钮上面显示的文字。第三个参数就是点击事件。
    1. 列表提示对话框

     //带四个列表项的对话框
                    final String[] items = new String[]{"123", "1233", "456", "789"};
                    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                    builder.setIcon(R.mipmap.ic_launcher);
                    builder.setTitle("请选择你喜欢的标题");
                    builder.setItems(items, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(MainActivity.this, "您选择了【" + items[which]
                                    + "】", Toast.LENGTH_SHORT).show();
                        }
                    });
                    builder.create().show();
    

    和普通对话框不一样的地方就是setItems,传入的第一个参数就是需要显示的内容,是一个字符串数组。第二个参数就是点击事件。

    这里还有个不一样的地方,就是普通对话是直接操作的AlertDialog对象,而这里是操作了一个AlertDialog内部类Builder对象。两者之间的关系就是Builder对象的create方法可以生成一个AlertDialog对象。

    1. 单选对话框

     final String[] items = new String[]{"1", "2", "3", "4", "5"};
                    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                    builder.setIcon(R.mipmap.ic_launcher);
                    builder.setTitle("请选择你喜欢的标题");
                    builder.setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(MainActivity.this, "您选择了【" + items[which]
                                    + "】", Toast.LENGTH_SHORT).show();
                        }
                    });
                    builder.setPositiveButton("确定", null);
                    builder.create().show();
    

    只是把setItems改成setSingleChoiceItems,同时多了一个参数,就是第二个0,这是默认选择的选择。这里使用

    • setPositiveButton:设置正面按钮,表示“积极”、“确认”的意思,第一个参数为按钮上显示的文字,下同;
    • setNegativeButton:设置反面按钮,表示“消极”、“否认”、“取消”的意思;
    • setNeutralButton:设置中立按钮;

    实现了AlertDialog.setButton的方法。

    1. 多选对话框

    final boolean[] checkedItem = new boolean[]{false,true,false,true,false};
                    final String[] items = new String[]{"1", "2", "3", "4", "5"};
                    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                    builder.setIcon(R.mipmap.ic_launcher);
                    builder.setTitle("请选择你喜欢的标题");
                    builder.setMultiChoiceItems(items, checkedItem, new DialogInterface.OnMultiChoiceClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                            checkedItem[which] = isChecked;
                        }
                    });
                    builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            String result = "";
                            for (int i = 0; i < checkedItem.length; i++) {
                                if (checkedItem[i]) {
                                    result+=items[i]+"";
                                }
                            }
                            if (!"".equals(result)) {
                                Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
                    builder.create().show();
    

    之前有Single,自然就有Multi,所以设置函数是setMultiChoiceItems。参数分别是显示文字数组,默认选项数组(boolean数组)和点击事件。

    ProgressDialog

    ProgressDialog和AlertDialog非常相似,只不过多了一个进度条,感觉更像是安装或者下载时候的提示。用法等于AlertDialog+ProgressBar相似。

    ——第一行代码
    注意,如果在setCancelable()中传人了false, 表示ProgressDialog是不能通过Back键取消掉的,这时你就一定要在代码中做好控制,当数据加载完成后必须要调用ProgressDialog 的dismiss ()方法来关闭对话框,否则ProgressDialog将会一直存在。

  • 相关阅读:
    web网络编程
    C++ 多线程*****(看书补充)
    C++信号处理
    预指令
    C++模板*******
    C++ 命名空间
    动态存储
    异常处理**********
    私钥、秘钥详解
    Pod控制器应用进阶
  • 原文地址:https://www.cnblogs.com/zllk/p/13363672.html
Copyright © 2011-2022 走看看