Android UI template design of the combined mode

Introduction: UI design has been programming in a very important part, but also the most part people crazy, good design requires constant revision, and constantly improve, then how can we reduce duplication of effort in UI design it, how when the design changes to reduce the workload of it, how to develop once, reuse it?

 The purpose of the article:

  1. Learn how to custom attributes
  2. Learn how to dynamically create components
  3. Learn how to design dynamic templates
  4. The convenience of experience developing templated
  5. Experience the interface callback mechanism of thought

1. How custom control?

The system is how to do? To RelativeLayout example:

Step One: Configure the desired properties in the atts.xml

<declare-styleable name="RelativeLayout">
        <attr name="gravity" />
        <attr name="ignoreGravity" format="reference" />
</declare-styleable>

<declare-styleable name="RelativeLayout_Layout">
        <attr name="layout_toLeftOf" format="reference" />
        <attr name="layout_toRightOf" format="reference" />
        <attr name="layout_above" format="reference" />
        <attr name="layout_below" format="reference" />
        <attr name="layout_alignBaseline" format="reference" />
        <attr name="layout_alignLeft" format="reference" />
        <!-- 其他属性省略了。。。 -->
</declare-styleable>

Step two: Rewrite control to meet their own requirements

The third step: Use the controls in the xml file

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".MainActivity">

</RelativeLayout>

1. Now we can follow the steps to customize our system of controls:

Effect Preview:

Button This control by the right and left and two intermediate TextView a combination.

Step 1: Create atts.xml, and configuration properties needed

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="Topbar">
        <attr name="title" format="string"/>
        <attr name="titleTextSize" format="dimension"/>
        <attr name="titleTextColor" format="color"/>
        <attr name="leftText" format="string"/>
        <attr name="leftTextColor" format="color"/>
        <attr name="leftBackground" format="reference|color"/>
        <attr name="rightText" format="string"/>
        <attr name="rightTextColor" format="color"/>
        <attr name="rightBackground" format="reference|color"/>
    </declare-styleable>
</resources>

The second step: to realize their View 

package com.lzw.topbar;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.RequiresApi;

/**
 * 顶部导航栏控件
 * 这是一个组合控件,由左右两个Button和一个TextView组成
 */
public class TopBar extends RelativeLayout {

    // 步骤2:定义需要使用的控件
    private Button leftButton , rightButton;
    private TextView tvTitle;

    // 步骤3:声明这些控件所需要使用的属性,即之前在 atts.xml 中定义的属性

    // 左 Button 属性
    private String leftText;
    private int leftTextColor;
    private Drawable leftBackground;

    // 右 Button 属性
    private String rightText;
    private int rightTextColor;
    private Drawable rightBackground;

    // 中间 TextView 属性
    private String title;
    private int titleTextColor;
    private float titleTextSize;

    private LayoutParams leftParams,rightParams,titleParams;

    private topbarClickListener listener;

    public interface topbarClickListener{
        void leftClick();
        void rightClick();
    }

    public void setOnTopBarClickListener(topbarClickListener listener){
        this.listener = listener;
    }

    //  不需要自定义属性的构造方法
    public TopBar(Context context) {
        super(context);
    }

    /**
     * 步骤1:添加构造方法
     *        需要自定义属性就使用这一个构造方法,使用atts参数
     * @param context
     * @param attrs
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    public TopBar(final Context context, AttributeSet attrs) {
        super(context, attrs);

        // 步骤4:给声明好的属性赋值,以将属性和控件关联
        // 4.1  通过TypedArray存储从xml文件中获取到的自定义属性的值,并赋给相应的变量
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TopBar);

        leftText = ta.getString(R.styleable.TopBar_leftText);
        leftTextColor = ta.getColor(R.styleable.TopBar_leftTextColor,0);
        leftBackground = ta.getDrawable(R.styleable.TopBar_leftBackground);

        rightText = ta.getString(R.styleable.TopBar_rightText);
        rightTextColor = ta.getColor(R.styleable.TopBar_rightTextColor,0);
        rightBackground = ta.getDrawable(R.styleable.TopBar_rightBackground);

        title = ta.getString(R.styleable.TopBar_title);
        titleTextSize = ta.getDimension(R.styleable.TopBar_titleTextSize,0);
        titleTextColor = ta.getColor(R.styleable.TopBar_titleTextColor,0);

        // 回收。1.避免浪费资源 2.避免由于缓存而引起的错误
        ta.recycle();

        // 4.2  实例化控件
        leftButton = new Button(context);
        rightButton = new Button(context);
        tvTitle = new Button(context);

        // 4.3  将属性值和控件关联
        leftButton.setText(leftText);
        leftButton.setTextColor(leftTextColor);
        leftButton.setBackground(leftBackground);

        rightButton.setText(rightText);
        rightButton.setTextColor(rightTextColor);
        rightButton.setBackground(rightBackground);

        tvTitle.setText(title);
        tvTitle.setTextSize(titleTextSize);
        tvTitle.setTextColor(titleTextColor);
        tvTitle.setGravity(Gravity.CENTER);
        tvTitle.setBackgroundColor(Color.argb(0,0,0,0));

        setBackgroundColor(0xFFF59563);

        //  步骤5:将控件放到layout中,通过LayoutParams控制摆放方式
        leftParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);

        addView(leftButton, leftParams);

        rightParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);

        addView(rightButton, rightParams);

        titleParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.MATCH_PARENT);
        titleParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);

        addView(tvTitle, titleParams);

        //  步骤6:动态控制 TopBar
        leftButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.leftClick();
            }
        });

        rightButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.rightClick();
            }
        });

    }

    /**
     * 是否显示左Button
     * @param flag
     */
    public void setLeftIsVisable(boolean flag){
        if(flag){
            leftButton.setVisibility(View.VISIBLE);
        }else {
            leftButton.setVisibility(View.GONE);
        }
    }

}

The third step: Use

In reference to a third party named in Android Studio Controls provided that: add xmlns: custom = "http://schemas.android.com/apk/res-auto" to

Namespace references to the re-named the custom, you can reference all the custom attributes through custom

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.lzw.topbar.TopBar
        android:id="@+id/topbar"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        custom:leftBackground="#03A9F4"
        custom:leftText="Back"
        custom:leftTextColor="#E91E63"
        custom:rightBackground="#03A9F4"
        custom:rightText="More"
        custom:rightTextColor="#E91E63"
        custom:title="自定义标题"
        custom:titleTextColor="#123412"
        custom:titleTextSize="8sp"></com.lzw.topbar.TopBar>

</RelativeLayout>

2. Use the TopBar in MainActivity

package com.lzw.topbar;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

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

        TopBar topBar = findViewById(R.id.topbar);
        topBar.setOnTopBarClickListener(new TopBar.topbarClickListener() {
            @Override
            public void leftClick() {
                Toast.makeText(MainActivity.this,"left",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void rightClick() {
                Toast.makeText(MainActivity.this,"right",Toast.LENGTH_SHORT).show();
            }
        });
        topBar.setLeftIsVisable(false);

    }
}

to sum up:

1. multiplexed by template interface callbacks improve development efficiency, to reduce the degree of coupling Code

2. Try to perfect template, accumulate more flexible, versatile template

3. The template is not limited to UI design, system architecture design codes can be used

4. The system encountered a problem you can think of Implementation

5. experience, think classic design patterns

Published 49 original articles · won praise 6 · views 1077

Guess you like

Origin blog.csdn.net/qq_36478274/article/details/104304741