android从放弃到坚持放弃第三课(上)

android 学习笔记——UI设计

注:学习内容均来自<第一行代码>

  • android 学习笔记UI设计
    • 常用控件的使用方法
      • TextView
      • Button
      • EditText
      • ImageView
      • ProgressBar
      • AlertDialog
      • ProgressDialog
    • 详解四种基本布局
      • 线性布局
      • 相对布局
      • 帧布局
      • 百分比布局
    • 创建自定义控件
      • 引入布局
      • 创建自定义控件
    • 问题


常用控件的使用方法

TextView


<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is TextView"
        />

LinearLayout>

LinearLayout是线性布局。

android:id定义了唯一标识。

android:width和android:height指定了控件的宽度和长度。

match_parent和fill_parent意义相同,但是更推荐前者,也就是由父布局来决定当前控件的大小。

wrap_content表示让当前的控件的大小能够刚好包含住里面的内容。

android:text指定了显示的文本内容。(默认是居左上角对齐)


<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="This is TextView"

        />

LinearLayout>

使用android:gravity来指定文字的对齐方式.可选值有top,bottom,left,right,center等,可以用|来同时指定多个值。

这里的center相当于center_vertical|center_horizontal.

还可以进行文字的大小和颜色的指定:


<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal|center_vertical"
        android:textSize="24sp"
        android:textColor="#08db98"
        android:text="This is TextView"

        />

LinearLayout>

大小单位是sp,颜色可以使用调色板。


Button

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

文字默认的是“BUTTON”,是因为系统会对Button中的所有引文字母自动进行大写转换。

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

禁用它。

我们之前使用的是匿名类。当然也可以这样:

““java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{

private static final String TAG = "MainActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button button2 = (Button) findViewById(R.id.Button_one);
    button2.setOnClickListener(this);
}
@Override
public void onClick(View v){
    switch (v.getId()){
        case R.id.Button_one:
            //
            break;
        default:break;
    }
}

}
““


EditText

    <EditText
        android:id="@+id/EditText_one"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:hint="Please input something"
        android:gravity="center"
        />

输入框的实现很人性化。

android:hint属性指定了一段提示性的文本。但输入的东西变多后,输入框会变宽。。

    <EditText
        android:id="@+id/EditText_one"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Please input something"
        android:gravity="center"
        android:maxLines="2"
        />

内容超过两行,文本会向上滚动,而EditText不会被拉伸。

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private static final String TAG = "MainActivity";
    private EditText editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = (EditText) findViewById(R.id.EditText_one);
        Log.d(TAG, "onCreate");
        if(savedInstanceState != null){
            String tempData = savedInstanceState.getString("data_key");
            Log.d(TAG,tempData);
        }
        Button button2 = (Button) findViewById(R.id.Button_one);
        button2.setOnClickListener(this);
    }
    public void onClick(View v){
        switch (v.getId()){
            case R.id.Button_one:
                String inputText = editText.getText().toString();
                Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_LONG).show();
                Log.d(TAG, " "+ R.id.Button_one);
                break;
            default:break;
        }
    }
}

//toString是为了把可能输入为数字的也转化为String.

跑路。


ImageView

ImageView是用于在界面上展示图片的控件。图片通常都是放在drawable开头的目录的,我们在res下新建一个drawable-xhdpi目录然后放入两张图片:

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

动态更改ImageView中的图片,通过修改MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private static final String TAG = "MainActivity";
    private EditText editText;
    private ImageView imageView;

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String tempData = "Something i just typed";
        outState.putString("data_key",tempData);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = (ImageView) findViewById(R.id.Image_one); 
        editText = (EditText) findViewById(R.id.EditText_one);
        Log.d(TAG, "onCreate");

        if(savedInstanceState != null){
            String tempData = savedInstanceState.getString("data_key");
            Log.d(TAG,tempData);
        }
        Button button2 = (Button) findViewById(R.id.Button_one);
        button2.setOnClickListener(this);

    }
    @Override
    public void onClick(View v){
        switch (v.getId()){
            case R.id.Button_one:
                imageView.setImageResource(R.drawable.img2);
                //String inputText = editText.getText().toString();
                //Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_LONG).show();
                Log.d(TAG, " "+ R.id.Button_one);
                break;
            default:break;
        }
    }
}

跑路;


ProgressBar

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_gravity="center"
        />

MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private static final String TAG = "MainActivity";
    private EditText editText;
    private ImageView imageView;
    private ProgressBar progressBar;


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String tempData = "Something i just typed";
        outState.putString("data_key",tempData);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        imageView = (ImageView) findViewById(R.id.Image_one);
        editText = (EditText) findViewById(R.id.EditText_one);
        Log.d(TAG, "onCreate");

        if(savedInstanceState != null){
            String tempData = savedInstanceState.getString("data_key");
            Log.d(TAG,tempData);
        }
        Button button2 = (Button) findViewById(Button_one);
        button2.setOnClickListener(this);

    }
    @Override
    public void onClick(View v){
        switch (v.getId()){
            case Button_one:

                if(progressBar.getVisibility() == View.GONE){
                    progressBar.setVisibility(View.VISIBLE);
                }else{
                    progressBar.setVisibility(View.GONE);
                }

                String inputText = editText.getText().toString();
                Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_LONG).show();
                Log.d(TAG, " "+ Button_one);
                imageView.setImageResource(R.drawable.img2);

                break;
            default:break;
        }
    }
}

可以换一个样式:

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        style="?android:attr/progressBarStyleHorizontal"
        android:max="100"
        />

顺带改一下MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private static final String TAG = "MainActivity";
    private EditText editText;
    private ImageView imageView;
    private ProgressBar progressBar;


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String tempData = "Something i just typed";
        outState.putString("data_key",tempData);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        imageView = (ImageView) findViewById(R.id.Image_one);
        editText = (EditText) findViewById(R.id.EditText_one);
        Log.d(TAG, "onCreate");

        if(savedInstanceState != null){
            String tempData = savedInstanceState.getString("data_key");
            Log.d(TAG,tempData);
        }
        Button button2 = (Button) findViewById(Button_one);
        button2.setOnClickListener(this);

    }
    @Override
    public void onClick(View v){
        switch (v.getId()){
            case Button_one:
                int progress = progressBar.getProgress();
                if(progress<100)progress += 10;
                else progress = 0;
                progressBar.setProgress(progress);

                String inputText = editText.getText().toString();
                Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_LONG).show();
                Log.d(TAG, " "+ Button_one);
                imageView.setImageResource(R.drawable.img2);

                break;
            default:break;
        }
    }
}

AlertDialog:

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

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private static final String TAG = "MainActivity";
    private EditText editText;
    private ImageView imageView;
    private ProgressBar progressBar;


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String tempData = "Something i just typed";
        outState.putString("data_key",tempData);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        imageView = (ImageView) findViewById(R.id.Image_one);
        editText = (EditText) findViewById(R.id.EditText_one);
        Log.d(TAG, "onCreate");

        if(savedInstanceState != null){
            String tempData = savedInstanceState.getString("data_key");
            Log.d(TAG,tempData);
        }
        Button button2 = (Button) findViewById(Button_one);
        button2.setOnClickListener(this);

    }
    @Override
    public void onClick(View v){
        switch (v.getId()){
            case Button_one:
                int progress = progressBar.getProgress();
                if(progress<100)progress += 10;
                else progress = 0;
                progressBar.setProgress(progress);

                String inputText = editText.getText().toString();
                Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_LONG).show();
                Log.d(TAG, " "+ Button_one);
                imageView.setImageResource(R.drawable.img2);

                AlertDialog.Builder dialog = new AlertDialog.Builder( MainActivity.this);
                dialog.setTitle("Error?");
                dialog.setMessage("Do you like huchi?");
                dialog.setCancelable(false);
                dialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
                   @Override
                    public void onClick(DialogInterface dialog, int which){
                       Toast.makeText(MainActivity.this, "I love you too", Toast.LENGTH_LONG).show();
                   }
                });
                dialog.setNegativeButton("No", new DialogInterface.OnClickListener(){
                    @Override
                    public void onClick(DialogInterface dialog, int which){
                        finish();
                    }
                });
                dialog.show();
                break;
            default:break;
        }
    }

通过AlertDialog.Builder创建一个AlertDialog的实例,然后可以为这个对话框设置标题,内容,可否取消等属性(即按Back键能否取消)。调用两个方法设置按钮的点击事件{可为空}。最后调用show()方法将对话框显示出来。跑路


ProgressDialog

和AlertDialog有点像。不同的是ProgressDialog会在对话空中显示一个进度条。用法也和AlertDialog比较像。

MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private static final String TAG = "MainActivity";
    private EditText editText;
    private ImageView imageView;
    private ProgressBar progressBar;


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String tempData = "Something i just typed";
        outState.putString("data_key",tempData);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        imageView = (ImageView) findViewById(R.id.Image_one);
        editText = (EditText) findViewById(R.id.EditText_one);
        Log.d(TAG, "onCreate");

        if(savedInstanceState != null){
            String tempData = savedInstanceState.getString("data_key");
            Log.d(TAG,tempData);
        }
        Button button2 = (Button) findViewById(Button_one);
        button2.setOnClickListener(this);

    }
    @Override
    public void onClick(View v){
        switch (v.getId()){
            case Button_one:
                int progress = progressBar.getProgress();
                if(progress<100)progress += 10;
                else progress = 0;
                progressBar.setProgress(progress);

                String inputText = editText.getText().toString();
                Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_LONG).show();
                Log.d(TAG, " "+ Button_one);
                imageView.setImageResource(R.drawable.img2);

                ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
                progressDialog.setTitle("Until you love me");
                progressDialog.setMessage("I'm waiting");
                progressDialog.setCancelable(true);
                progressDialog.show();

//                AlertDialog.Builder dialog = new AlertDialog.Builder( MainActivity.this);
//                dialog.setTitle("Error?");
//                dialog.setMessage("Do you like huchi?");
//                dialog.setCancelable(false);
//                dialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
//                   @Override
//                    public void onClick(DialogInterface dialog, int which){
//                       Toast.makeText(MainActivity.this, "I love you too", Toast.LENGTH_LONG).show();
//                   }
//                });
//                dialog.setNegativeButton("No", new DialogInterface.OnClickListener(){
//                    @Override
//                    public void onClick(DialogInterface dialog, int which){
//                        finish();
//                    }
//                });
//                dialog.show();
                break;
            default:break;
        }
    }
}

同样的道理,同样的跑路,嘿嘿嘿。


详解四种基本布局

界面总是由很多控件组成,为了让控件有条不絮的摆放,就需要借助布局来实现。


线性布局

LinearLayout布局也就是线性布局,也就是我们之前一直用的布局。

既然是线性排序,就不应该只有一个方向,但为什么我们的控件都是在垂直方向排列的呢?

android:orientation="vertical"就是这句话。指定了排列方向是vertical,聪明的你肯定早就发现没有这句话就会报错。

如果指定的是horizontal即水平方向排列。

你可以自己体验一下,因为不是很好,代码就不贴了。

主要的是android:layout_gravity应选(top,center_vertical,bottom);

还有一个重要的属性是android:layout_weight.这个属性允许我们使用比例的方式来指定控件的大小,它在手机屏幕的适配性方面可以起到非常重要的作用。所以我还是贴一点代码吧:


<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <EditText
        android:id="@+id/input_message"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="1"
        />

    <Button
        android:id="@+id/send"
        android:layout_width="0dp"
        android:layout_height="wrap_content" 
        android:layout_weight="1"
        android:text="Send"
        android:textAllCaps="false"
        />
LinearLayout>

    <LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

        <ImageView
            android:id="@+id/Show_you"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:src="@drawable/img3"
            />

    LinearLayout>

LinearLayout>

我贴了我一张特别好看的照片,哈哈哈。(●’◡’●)

layout_weight的值其实代表所占的比例。

上面的是1:1自然是各占一半。


相对布局

RelativeLayout即相对布局,也很常用。和LinearLayout的排列规则不同,更加随意。

贴代码:


<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <Button
        android:id="@+id/Button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="1"
        />

    <Button
        android:id="@+id/Button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:text="2"
        />

    <Button
        android:id="@+id/Button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:text="3"
        />
    <Button
        android:id="@+id/Button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:text="4"
        />

    <Button
        android:id="@+id/Button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="5"
        />


RelativeLayout>

虽然这些属性都没见过,但是这不重要,看看生成的图和属性的名字我们就知道他们的意思是什么。再来改一下


<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <Button
        android:id="@+id/Button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/Button5"
        android:layout_toLeftOf="@id/Button5"
        android:text="1"
        />

    <Button
        android:id="@+id/Button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/Button5"
        android:layout_toRightOf="@id/Button5"
        android:text="2"
        />

    <Button
        android:id="@+id/Button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/Button5"
        android:layout_toLeftOf="@id/Button5"
        android:text="3"
        />
    <Button
        android:id="@+id/Button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/Button5"
        android:layout_toRightOf="@id/Button5"
        android:text="4"
        />

    <Button
        android:id="@+id/Button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="5"
        />


RelativeLayout>

在修改属性的时候,我们发现其他四个button有一个→指向5.

属性虽多,但是规律可循


帧布局

FrameLayout即帧布局。他比较少用也很简单。


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:text="This is a new Text"
        />

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:src="@mipmap/ic_launcher"
        />

FrameLayout>

可以发现文字和图片是有重叠的。可以使用layout_gravity属性来指定控件在布局中的对齐方式。


百分比布局

细心的你也许发现,只有LinearLayout才支持layout_weight。比如说让RelativeLayout来单独实现两个按钮平分布局宽度的效果是比较困难的。百分比布局,和网页的很相似。

我们可以不再使用wrap_content和match_parent等方式来指定控件的大小。而是允许直接指定控件在布局中所占的百分比,这样就可以轻易实现平分布局或任意比例分割布局的效果。

由于LinearLayout已经支持按比例指定控件大小,因此百分比布局只为FrameLayout和RelativeLayout布局进行功能扩展,提供了PercentFrameLayout和PercentRelativeLayout这两个全新的布局。

找到左测里app目录下,打开build.grade文件,在dependencies闭包添加

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.0'
    compile 'com.android.support:percent:25.3.0'
    testCompile 'junit:junit:4.12'
}

注意appcompat版本需和percent那个相同

此时需要点一个Sync Now;


<android.support.percent.PercentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Button 
        android:id="@+id/Button_1"
        android:text="Button1"
        android:layout_gravity="left|top"
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        />

    <Button
        android:id="@+id/Button_2"
        android:text="Button2"
        android:layout_gravity="right|top"
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        />

    <Button
        android:id="@+id/Button_3"
        android:text="Button3"
        android:layout_gravity="left|bottom"
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        />

    <Button
        android:id="@+id/Button_4"
        android:text="Button4"
        android:layout_gravity="right|bottom"
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        />

最外层使用了PercentFrameLayout,由于百分比布局并不是内置在系统SDK中吗所以需要完整的把包路径写出来。然后还要定义一个app的命名空间xmlns:app="http://schemas.android.com/apk/res-auto"

显然定义了四个按钮,使用了app:layout_heightPercent等属性指定了高度。

不过PercentFrameLayout还是继承了FrameLayout的特性,即所有的控件默认都是摆放在布局的左上角。但还是可以借助layout_gravity来分别将这4个按钮放置。

还有一个PercentRelativeLayout也一样。


创建自定义控件

控件和布局的继承关系:

android从放弃到坚持放弃第三课(上)_第1张图片

view是android中最基本的一种UI组件,可以在屏幕上绘制一块矩形区域,并能响应这块区域的各种事件,因此,我们使用的各种控件其实就是在View的基础之上又添加了各自特有的功能。

当系统自带的空间不够满足需求时,可以利用上面的继承结构来创建自定义控件。


引入布局

可能你已经发现我们之前创建的xml布局中,标题栏是不一样的,而这和我们平常所见的却很是不同。

如果在每一个活动的布局中都写一遍同样的标题栏代码,着实太费劲。这是就可以使用引入布局。

新建title.xml:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/img3">

    <Button
        android:id="@+id/title_back"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        android:text="Back"
        android:textColor="#fff"
        />
    <TextView
        android:id="@+id/title_text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_weight="1"
        android:gravity="center"
        android:text="Title text"
        android:textSize="24sp"
        android:textColor="#fff"
        />

    <Button
        android:id="@+id/title_edit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        android:text="Edit"
        android:textColor="#fff"
        />

LinearLayout>

分别加入了两个button和一个TextView。可用于返回。书上有给布局增加android:backgroud属性。

另外我们使用了android:margin属性。可以指定控件在上下左右方向上偏离的距离。当然也可以使用android:layout_marginLeft这种的。

在其他xml文件中想引入此布局,只需要在布局中具体如下:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context="com.example.wrjjrw.activitylifeactivity.MainActivity"
    android:weightSum="1">

    <include layout="@layout/title"/>
LinearLayout>

最后别忘了隐藏系统自带的标题栏。MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActionBar actionbar = getSupportActionBar();
        if(actionbar != null){
            actionbar.hide();
        }
    }
}

调用了getSupportActionBar()方法获得ActionBar的实例。在调用它的hide方法。跑路。完成。


创建自定义控件

引入布局的技巧确实解决了重复编写代码布局的问题。但是如果布局中有一些控件要求能够响应事件,我们还是需要在每一个活动中为这些控件单独写一次事件注册的代码。比如说标题栏中的返回按钮。不管在哪一个活动中,这个按钮的功能都是相同的,都是销毁当前的活动。用相同的方法。我们自定义控件。

新建TitleLayout继承LinearLayout,让他成为我们自定义的标题栏控件。

public class TitleLayout extends LinearLayout {
    public TitleLayout (Context context , AttributeSet attrs){
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.title, this);

        Button titleBack = (Button) findViewById(R.id.title_back);
        titleBack.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                ((Activity) getContext()).finish();
            }
        });

        Button titleEdit = (Button) findViewById(R.id.title_edit);
        titleEdit.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Toast.makeText(getContext(), "Acess denied", Toast.LENGTH_LONG).show();
            }
        });

    }
}

LayoutInflater;

public View inflate (int resource, ViewGroup root)

Inflate a new view hierarchy from the specified xml resource. Throws InflateException if there is an error.

​-Parameters

resource ID for an XML layout resource to load (e.g., R.layout.main_page)
root Optional view to be the parent of the generated hierarchy.

​-Returns

  • The root View of the inflated hierarchy. If root was supplied, this is the root View; otherwise it is the root of the inflated XML file.

public static LayoutInflater from (Context context)

Obtains the LayoutInflater from the given context.

这就是我们自己写的自定义控件。我们重写了他的构造函数,在布局中引入了TitleLayout便会调用这个函数。然后在狗仔函数中需要对标题栏布局进行动态加载。这里需要借助LayoutInflater来实现。通过LayoutInflater的from()方法可以构建一个LayoutInflater对象。然后调用inflate()方法进行动态加载。他的两个参数分别是布局文件的id,和父布局。

自定义空间已经创建好了,然后为之写了事件。

现在对父布局惊醒修改:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.wrjjrw.activitylifeactivity.MainActivity"
    android:weightSum="1">

    <com.example.wrjjrw.activitylifeactivity.TitleLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        />

LinearLayout>

将之前的include改成了现在的,包名在这里不可省略。跑路。。。

当然之后也就用上面的那个方法了。include的话不能起到启动事件的作用。


问题:

问:怎么查api文档关于控件的东西啊?

答:android从放弃到坚持放弃第三课(上)_第2张图片

你可能感兴趣的:(从入门到giveup)