自定义控件
我们需要的步骤:
*设计需要的属性
*实现VIew
*引用VIew
*完善功能
本文我们自定义一个Topbar的控件,需要实现有两个按钮,一个标题的控件。可参考企鹅的移动端界面Topbar(虽然没有那么高大上),具体为一个居左的返回键,一个居右菜单键,一个居中标题。
1,设计需要的属性
在valuse中新建一个名为atts的xml文件,然后将我们需要用到的属性全都写在里面。
<resources>
<declare-styleable name="Topbar">
<attr name="title" format="string" />
<attr name="titleTextSize" format="dimension" />
<attr name="titleTextColor" format="color" />
<attr name="leftTextColor" format="color" />
<attr name="leftBackground" format="reference|color" />
<attr name="leftText" format="string" />
<attr name="rightTextColor" format="color" />
<attr name="rightBackground" format="reference|color" />
<attr name="rightText" format="string" />
</declare-styleable>
</resources>
如上,首先是Topbar名字,然后是属性,自定义好名称,format为指定属性的类型,如leftText为左边返回键的文字,所以为string类型。
这里需要注意:自定义的leftBackground为左边返回按钮的背景属性,背景属性是可以引用资源文件夹里面的文件的,所以在指定类型的时候指定类型为reference|color,即可以为颜色类型也可以引用资源文件。
2,实现VIew
新建一个Topbar类继承RelativeLayout
实现构造方法,
声明属性然后把自定义xml中定义的属性值映射到这里自定义的属性中去。
private Button leftButton, rightButton;
private TextView tvTitle;
private int leftTextColor;
private Drawable leftBackground;
private String leftText;
private int rightTextColor;
private Drawable rightBackground;
private String rightText;
private String title;
private float titleTextSize;
private int titleTextColor;
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.Topbar);
leftTextColor = ta.getColor(R.styleable.Topbar_leftTextColor, 0);
leftBackground = ta.getDrawable(R.styleable.Topbar_leftBackground);
leftText = ta.getString(R.styleable.Topbar_leftText);
rightTextColor = ta.getColor(R.styleable.Topbar_rightTextColor, 0);
rightBackground = ta.getDrawable(R.styleable.Topbar_rightBackground);
rightText = ta.getString(R.styleable.Topbar_rightText);
title = ta.getString(R.styleable.Topbar_title);
titleTextSize = ta.getDimension(R.styleable.Topbar_titleTextSize, 0);
titleTextColor = ta.getColor(R.styleable.Topbar_titleTextColor, 0);
每一个属性都能找到我们自定义的属性。
初始化控件,然后设置属性,再给属性初始化,添加到View中。
leftButton = new Button(context);
rightButton = new Button(context);
tvTitle = new TextView(context);
leftButton.setTextColor(leftTextColor);
leftButton.setBackground(leftBackground);
leftButton.setText(leftText);
rightButton.setTextColor(rightTextColor);
rightButton.setBackground(rightBackground);
rightButton.setText(rightText);
tvTitle.setText(title);
tvTitle.setTextColor(titleTextColor);
tvTitle.setTextSize(titleTextSize);
// 设置居中
tvTitle.setGravity(Gravity.CENTER);
setBackgroundColor(0xFFF59563);
// 设置宽高
leftParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// 设置对齐方式
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
// 将leftParams这个布局加入到leftButton里面
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);
由上面可见,我们给控件设置了宽高的属性,然后添加了左对齐与右对齐的方式。重点是添加这些属性与规则的方法。
以上我们就已经完成了自定义控件,接下来就是在布局中用我们的控件。
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
首先我们要在布局中加入着两居,第一句是布局自带的我们可以不管,第二句使我们要注意的,而且名字不能与第一句相同。
<com.example.administrator.zidingyi.Topbar
android:id="@+id/topbar"
android:layout_width="match_parent"
android:layout_height="40dp"
custom:leftBackground="#3DBCFD"
custom:leftText="返回"
custom:leftTextColor="#FFFFFF"
custom:rightBackground="#3DBCFD"
custom:rightText="菜单"
custom:rightTextColor="#FFFFFF"
custom:title="标题"
custom:titleTextColor="#123412"
custom:titleTextSize="10dp">
</com.example.administrator.zidingyi.Topbar>
最后来给我们的按钮加上点击事件,接口回调的方法实现我们的按钮只实现点击不实现事件,将点击之后的事件交给模块之外。
// 写一个接口
public interface topbarClickListener { public void leftCliuc(); public void rightCliuc(); } public void setOnTopbarClickLstener(topbarClickListener listener) { this.listener = listener; } 写点击事件时候只需要将接口中的方法写进去:private topbarClickListener listener;
然后点击将要实现的事件我们写在主函数中:leftButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { listener.leftClick(); } }); rightButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { listener.rightClick(); } });
Topbar topbar = (Topbar) findViewById(R.id.topbar); topbar.setOnTopbarClickLstener(new Topbar.topbarClickListener() { @Override public void leftClick() { Toast.makeText(MainActivity.this, "左边", Toast.LENGTH_SHORT).show(); } @Override public void rightClick() { Toast.makeText(MainActivity.this, "右边", Toast.LENGTH_SHORT).show(); } });
以下是完整代码:
XML:
<?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:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.administrator.zidingyi.MainActivity"> <com.example.administrator.zidingyi.Topbar android:id="@+id/topbar" android:layout_width="match_parent" android:layout_height="40dp" custom:leftBackground="#3DBCFD" custom:leftText="返回" custom:leftTextColor="#FFFFFF" custom:rightBackground="#3DBCFD" custom:rightText="菜单" custom:rightTextColor="#FFFFFF" custom:title="标题" custom:titleTextColor="#123412" custom:titleTextSize="10dp"> </com.example.administrator.zidingyi.Topbar> </RelativeLayout>
atts:
Topbar:<?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="leftTextColor" format="color" /> <attr name="leftBackground" format="reference|color" /> <attr name="leftText" format="string" /> <attr name="rightTextColor" format="color" /> <attr name="rightBackground" format="reference|color" /> <attr name="rightText" format="string" /> </declare-styleable> </resources>
import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.annotation.RequiresApi; 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; /** * 1、定义需要的控件 * 2、定义于atts里面相对应的变量 * 3、将变量与atts里面的属性名字绑定 * 4、初始化控件,将每一个属性赋予对应的控件 * 5、定义控件在布局中的排布 */ public class Topbar extends RelativeLayout { private Button leftButton, rightButton; private TextView tvTitle; private int leftTextColor; private Drawable leftBackground; private String leftText; private int rightTextColor; private Drawable rightBackground; private String rightText; private String title; private float titleTextSize; private int titleTextColor; // 设置三个需要的布局,分别是左边的 中间的 右边的 private LayoutParams leftParams, rightParams, titleParams; private topbarClickListener listener; // 写一个接口 public interface topbarClickListener { public void leftClick(); public void rightClick(); } // 接口 public void setOnTopbarClickLstener(topbarClickListener listener) { this.listener = listener; } @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) public Topbar(final Context context, AttributeSet attrs) { super(context, attrs); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.Topbar); leftTextColor = ta.getColor(R.styleable.Topbar_leftTextColor, 0); leftBackground = ta.getDrawable(R.styleable.Topbar_leftBackground); leftText = ta.getString(R.styleable.Topbar_leftText); rightTextColor = ta.getColor(R.styleable.Topbar_rightTextColor, 0); rightBackground = ta.getDrawable(R.styleable.Topbar_rightBackground); rightText = ta.getString(R.styleable.Topbar_rightText); title = ta.getString(R.styleable.Topbar_title); titleTextSize = ta.getDimension(R.styleable.Topbar_titleTextSize, 0); titleTextColor = ta.getColor(R.styleable.Topbar_titleTextColor, 0); // 回收 ta.recycle(); leftButton = new Button(context); rightButton = new Button(context); tvTitle = new TextView(context); leftButton.setTextColor(leftTextColor); leftButton.setBackground(leftBackground); leftButton.setText(leftText); rightButton.setTextColor(rightTextColor); rightButton.setBackground(rightBackground); rightButton.setText(rightText); tvTitle.setText(title); tvTitle.setTextColor(titleTextColor); tvTitle.setTextSize(titleTextSize); // 设置居中 tvTitle.setGravity(Gravity.CENTER); setBackgroundColor(0xFFF59563); // 设置宽高 leftParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); // 设置对齐方式 leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE); // 将leftParams这个布局加入到leftButton里面 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); leftButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { listener.leftClick(); } }); rightButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { listener.rightClick(); } }); } }
MainActivity:import android.support.v7.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 = (Topbar) findViewById(R.id.topbar); topbar.setOnTopbarClickLstener(new Topbar.topbarClickListener() { @Override public void leftClick() { Toast.makeText(MainActivity.this, "左边", Toast.LENGTH_SHORT).show(); } @Override public void rightClick() { Toast.makeText(MainActivity.this, "右边", Toast.LENGTH_SHORT).show(); } }); } }