《第一行代码》阅读记录—UI设计

来源:互联网 发布:java bigdecimal加法 编辑:程序博客网 时间:2024/05/29 10:30

一、序

这是一系列关于第一行代码的博文,上一篇我们有写最基本的四大组件,以及其主要用法,这一篇是以android的一个重要的组成部分——view为主要内容展开,在此,也会将fragment(碎片)添加一起讲解。

二、常用控件

说到view,不得不提的是一些我们经常用到的控件,如下:

TextView

我们使用android:gravity 来指定文字的对齐方式,可选值有top、bottom、left、right、center等, 可以用| 来同时指定多个值, 指定center , 效果等同于center_vertical|center_horizontal,表示文字在垂直和水平方向都居中对齐。通过android:textSize 属性可以指定文字的大小,通过android:textColor 属性可以指定文字的颜色。

Button

当点击按钮时,就会执行监听器中的onClick()方法,我们只需要在这个方法中加入待处理的逻辑就行了。除了前面所使用匿名类的方式来注册监听器,也可以使用实现接口的方式来进行注册,代码如下所示:

public class MainActivity extends Activity implements OnClickListener {    private Button button;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        button = (Button) findViewById(R.id.button);        button.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId()) {        case R.id.button:            // 在此处添加逻辑            break;        default:            break;        }    }}

EditText

用于和用户进行交互的另一个重要控件,允许用户在控件里输入和编辑内容,并可以在程序中对这些内容进行处理。通过android:hint属性设置 提示性文字。

通过android:maxLines属性 指定了EditText 的最大行数,这样当输入的内容超过设置值时,文本就会向上滚动,而EditText 则不会再继续拉伸。

获得EditText中的内容,首先通过findViewById()方法得到EditText 的实例,然后在按钮的点击事件里调用EditTextgetText()方法获取到输入的内容,再调用toString()方法转换成字符串。

ImageView

ImageView 是用于在界面上展示图片的一个控件。使用android:src 属性给ImageView 指定了一张图片,在程序中通过代码动态地更改ImageView 中的图片:

ImageView imageView = (ImageView)findViewById(R.id.image_view);imageView.setImageResource(R.drawable.jelly_bean);

ProgressBar

ProgressBar 用于在界面上显示一个圆形进度条(旋转),表示我们的程序正在加载一些数据。还可以给ProgressBar 指定不同的样式,刚刚是圆形进度条,通过style 属性可以将它指定成水平进度条。通过android:max 属性给进度条设置一个最大值。

style="?android:attr/progressBarStyleHorizontal"android:max="100"

在代码中动态地更改进度条的进度。修改MainActivity 中的代码,如下所示:

 public class MainActivity extends Activity implements OnClickListener {    ……    @Override    public void onClick(View v) {        switch (v.getId()) {        case R.id.button:            int progress = progressBar.getProgress();            progress = progress + 10;            progressBar.setProgress(progress);            break;        default:            break;        }    }}

每点击一次按钮,我们就获取进度条的当前进度,然后在现有的进度上加10 作为更新后的进度。

AlertDialog

AlertDialog 可以在当前的界面弹出一个对话框,这个对话框是置顶于所有界面元素之上的,能够屏蔽掉其他控件的交互能力,因此一般AlertDialog 都是用于提示一些非常重要的内容或者警告信息。比如为了防止用户误删重要内容,在删除前弹出一个确认对话框。

public class MainActivity extends Activity implements OnClickListener {    ……    @Override    public void onClick(View v) {        switch (v.getId()) {        case R.id.button:            AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);            dialog.setTitle("This is Dialog");//标题            dialog.setMessage("Something important.");//信息            dialog.setCancelable(false);//可否取消(true点击空白处,Back键消失)            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();//将对话框显示出来            break;        default:            break;        }    }}

ProgressDialog

ProgressDialogAlertDialog 有点类似,都可以在界面上弹出一个对话框,都能够屏蔽掉其他控件的交互能力。不同的是,ProgressDialog 会在对话框中显示一个进度条,一般是用于表示当前操作比较耗时,让用户耐心地等待。

public class MainActivity extends Activity implements OnClickListener {    ……    @Override    public void onClick(View v) {//几个方法同上        switch (v.getId()) {        case R.id.button:            ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);            progressDialog.setTitle("This is ProgressDialog");            progressDialog.setMessage("Loading...");            progressDialog.setCancelable(true);//如果false不能Back键取消,一直存在,需要在代码中控制//当数据加载完成后必须要调用ProgressDialog 的dismiss()方法来关闭对话框            progressDialog.show();            break;        default:            break;        }    }}

Android 控件的可见属性

所有的Android 控件都具有这个属性,可以通过android:visibility进行指定,可选值有三种,visible、invisible 和gone。

  • visible 表示控件是可见的,这个值是默认值,不指定android:visibility 时,控件都是可见的。
  • invisible 表示控件不可见,但是它仍然占据着原来的位置和大小,可以理解成控件变成透明状态了。
  • gone 则表示控件不仅不可见,而且不再占用任何屏幕空间。

我们还可以通过代码来设置控件的可见性,使用的是setVisibility()方法,可以传入View.VISIBLE、View.INVISIBLE 和View.GONE 三种值。

三、基本布局

1.LinearLayout 线性布局

这个布局中会将所包含的控件在线性方向进行依次排列。通过android:orientation属性指定排列方向是vertical还是horizontal ,即垂直和水平方向。

注意如果指定orientationvertical,那么控件高度绝对不能为match_parent,因为这样单独一个控件就把整个垂直方向铺满,其他控件就没有摆放位置了。同理如果orientationhorizontal,那么控件宽度不能为match_parent 。另外如果不指定orientation,默认是horizontal。

android:layout_gravity 用于指定控件在布局中的对齐方式。注意android:gravity是用于指定文字在布局中的对齐方式当LinearLayout排列方向是horizontal时,只有垂直方向的对齐才生效,因为此时水平方向长度不固定,每添加一个控件水平方向长度都会改变,因此无法指出水平方向对齐方式,反之,当LinearLayout排列方向是vertical,那么只有水平方向对齐才生效。

android:layout_weight,这个属性允许我们使用比例方式来指定控件大小,在 手机屏幕适配性上有很重要作用。修改activity_main.xml,让其在水平方向1:1显示一个输入框和按钮,如下:

<EditText    android:layout_width="0dp"    android:layout_height="wrap_content"    android:layout_weight="1" /><Button    android:layout_width="0dp"    android:layout_height="wrap_content"    android:layout_weight="1"    android:text="one"    android:id="@+id/button1" />

我们将两个控件的水平方向宽度都设为0,因为这时我们的编辑框和按钮宽度由layout_weight来决定,把宽度设为0是一种比较规范的写法。会按1:1比例显示两个控件的原理:系统将LinearLayout下所有控件指定的layout_weight相加,得到一个总值,每个控件所占大小比例就是用该控件的layout_weight除以总值。如果想要EditText占3/5,Button占2/5,只需要把EditTextlayout_weight设为3,Buttonlayout_weight设为2。

<EditText    android:layout_width="0dp"    android:layout_height="wrap_content"    android:layout_weight="1" /><Button    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="one"    android:id="@+id/button1" />

我们仅仅指定EditTextlayout_weight,并将Button的宽度改回wrap_content.这表示Button宽度仍然按wrap_content算,EditText会铺满屏幕剩余空间。使用这种方式编写界面,不仅屏幕适配性非常好,而且看起来更加舒服。

2.RelativeLayout 相对布局

设置5个按钮,分别在左上,右上,中间,左下,右下。

按钮1:

android:layout_alignParentLeft="true"android:layout_alignParentTop="true"

按钮2:

android:layout_alignParentRight="true"android:layout_alignParentTop="true"

按钮3:

android:layout_centerInParent="true"

按钮4:

android:layout_alignParentLeft="true"android:layout_alignParentBottom="true"

按钮5:

android:layout_alignParentRight="true"android:layout_alignParentBottom="true"

上面的都是相对于父布局进行定位的。也可以相对于控件进行定位:

我们来设置id:显示为one按钮在中间,其它按钮相对于one按钮布局在四周
one:

android:id="@+id/one"android:layout_centerInParent="true"

two:

android:id="@+id/two"android:layout_above="@+id/one"android:layout_toLeftOf="@+id/one"

three:

android:id="@+id/three"android:layout_above="@+id/one"android:layout_toRightOf="@+id/one"

four:

android:id="@+id/four"android:layout_below="@+id/one"android:layout_toLeftOf="@+id/one"

five:

android:id="@+id/five"android:layout_below="@+id/one"android:layout_toRightOf="@+id/one"

我们一个控件引用另一个控件id时,该控件一定要定义在引用控件之后,否则会出现找不到id情况。

其它属性:

  • android:layout_alignLeft 一个控件左边缘与另一个控件左边缘对齐
  • android:layout_alignRight一个控件右边缘与另一个控件右边缘对齐
  • android:layout_alignTop 一个控件上边缘与另一个控件上边缘对齐
  • android:layout_Bottom 一个控件下边缘与另一个控件下边缘对齐

3.FrameLayout

这种布局没有定位方式,所有的控件都摆在布局的左上角。修改activity_main.xml:

<Button    android:id="@+id/one"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="one" /><ImageView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:src="@drawable/ic_launcher" />

4.TableLayout

TableLayout允许我们用排列表格的方式排列控件。我们设计一个界面:

<TableRow>     <TextView         android:layout_height="wrap_content"         android:text="Account" />     <EditText         android:id="@+id/account"         android:layout_height="wrap_content"         android:hint="Input your account" /> </TableRow> <TableRow>     <TextView         android:layout_height="wrap_content"         android:text="Password" />     <EditText         android:id="@+id/password"         android:layout_height="wrap_content"         android:inputType="textPassword" /> </TableRow> <TableRow>     <Button         android:id="@+id/login"         android:layout_height="wrap_content"         android:layout_span="2"         android:text="Login" /> </TableRow>

每个代表表格的一行中的每个控件代表一列,我们把android:inputType设为textPasswordEditText变为密码输入框,第三行只有一个按钮,只有一列。我们将单元格合并,使用android:layout_span="2"让登陆按钮占两列不过上面登陆界面没有充分利用屏幕宽度,右侧空了一块。
TableRow中无法指定控件的宽度,这时候使用android:stretchColumns属性就可以很好的解决问题,它允许将TableLayout中的某一列进行拉伸,达到自动适应屏幕宽度的作用。

<?xml version="1.0" encoding="utf-8"?><TableLayout 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:stretchColumns="1"

android:stretchColumns设为1,表示如果表格不能占满屏幕宽度,就将第二列拉伸至屏幕宽度。注意这里是从0开始的,0代表第一列,1代表第二列。

四、自定义控件

控件和布局的继承结构:

自定义view的基本流程:

对外提供操作方法和监听回调

自定义完View之后,一般会对外暴露一些接口,用于控制View的状态等,或者监听View的变化,也就是定义接口。我们类似于Button的点击事件就是这样的原理。

自定义View的分类

  • 在原有的控件基础上扩展,比如继承ImageView去实现圆形头像等。
  • 通过组合控件来自定义View,比如标题栏就可以通过组合控件来实现,左边一个返回按钮,中间一个显示文本,右边可有可无的提交按钮。
  • 完全重写onDraw()自定义View。

五、Fragment(碎片)

让我们来看看fragment的活动周期:

与 Activity 的 关系

Fragment 必须是依存于 Activity 而存在的,因此 Activity 的生命周期会直接影响到 Fragment 的生命周期。Android 官网这张图很好的说明了两者生命周期的关系。

Activity 比较,多了下面几个回调函数:

1.onAttach(),当 Fragment 和 Activity 建立关联时调用。
2.onCreateView(),当为 Fragment 创建视图时调用。
3.onActivityCreated(),与 Fragment 关联的 Activity 已经创建完毕时调用。
4.onDEstroyView(),当与 Fragment 关联的视图被移除时调用。
5.onDetach(),当 Fragment 和 Activity 接触关联是调用。

六、结

以上就是我对于第一行代码中关于view和自定义view以及fragment的认识与理解,共勉!

0 0
原创粉丝点击