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

一、序

这是一系列关于第一行代码的博文,上一篇我们有写最基本的四大组件,以及其主要用法,这一篇是以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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值