Andriod自定义组件

    在最近几天,经常被他人问道Android自定义组件的知识,心里有个大概的框架,但有时有语言描述时,感觉却无从开口。查询资料时感觉有点杂乱,所以今天把自定义组件的资料整理一下。

     自定义组件是在Android开发经常用到,当系统预定义的组件无法满足开发的需求时,或者开发过程中存在类似组件复用时,就可以将其复用的组件自定义成为模板,减少代码的冗余,提高代码的复用。

    自定义组件可以分为两种:一种是自定义View,另一种则就是自定义ViewGroup.。

    这两种自定义组件的流程大指差不多,但其细节却存在很大的异同。下面我简单的书写一下自定义组件的流程

      (1)根据需求确定自定义组件的类型

      (2)根据所需的自定义组件的类型及其开发的需求确定自定义属性

      (3)根据需求重新 onMeasure,onLayout,onDraw方法。注意:防止wrap_content和padding失效

      (4)如果是自定义ViewGroup,则需要防止滑动冲突。


 上述仅是提供自定义组件的开发过程的参考,其中防止wrap_content和padding失效涉及到View的工作流程,防止滑动冲突涉及到时间分发机制。我将在后续详细讲解其知识。下面我将通过一种小demo来总结一下上述的知识。

    此demo为自定义ViewGroup,也成为自定义的组合模式:

    其最终的效果如下:


其实现步骤如下

    1、在res目录下的values目录创建自定义属性文件attrs

   2、实现自定义属性,其中自定义的属性为左边Button的背景,字体颜色,字体大小;右边Button的背景,字体颜色,字体大小,中

间title的背景,字体颜色,字体大小:源码如下:

<?xml version="1.0" encoding="utf-8"?>

<!--设置自定义组件的属性-->
<resources>

    <declare-styleable name="topBar">

        <attr name="titleText" format="string"></attr>
        <attr name="titleTextSize" format="dimension"></attr>
        <attr name="titleColor" format="color"></attr>
        <attr name="titleBackground" format="color|reference"></attr>
        <attr name="leftText" format="string"></attr>
        <attr name="leftTextColor" format="color"></attr>
        <attr name="leftTextSize" format="dimension"></attr>
        <attr name="leftBackground" format="color|reference"></attr>
        <attr name="rightText" format="string"></attr>
        <attr name="rightTextSize" format="dimension"></attr>
        <attr name="rightTextColor" format="color"></attr>
        <attr name="rightBackground" format="color|dimension"></attr>
    </declare-styleable>


</resources>

3、自定义ViewGroup,实现其构造函数,关联自定义属性,源码如下:

  1)自定义组件的类名     

 public class TopBar extends RelativeLayout 

   2)自定义组件的所关联属性的成员变量

private String titleText;
private int titleTextSize;
private int titleColor;
private Drawable titleBackground;


private String leftText;
private int leftTextColor;
private int leftTextSize;
private Drawable leftBackground;


private String rightText;
private int rightTextColor;
private int rightTextSize;
private Drawable rightBackground;
private Button leftButton;
private Button rightButton;
private TextView titleTextView;


private LayoutParams leftLayoutParams;
private LayoutParams rightLayoutParams;
private LayoutParams titleLayoutParams;


private TopBarClickListener listener;

3)重写自定义组件的构造函数,关联自定义属性


/**
 * 实现TopbBar的构造函数用于关联自定义属性
 */
public TopBar(Context context, AttributeSet attrs) {
    super(context, attrs);


    relevanceAttr(context, attrs);
    relevanceView(context, attrs);
    topBarClickListener();


}

/**
 * @param context
 * @param attrs
 * @return void
 * 关联自定义属性
 */
private void relevanceAttr(Context context, AttributeSet attrs) {


    /**
     * attrs 自定义的资源文件
     *
     *
     * R.styleable.topBar 自定义的属性资源名
     *
     *
     * 关联自定义属性文件,将自定义属性保存在该集合里面
     * */
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.topBar);


    titleText = ta.getString(R.styleable.topBar_titleText);
    titleTextSize = (int) ta.getDimension(R.styleable.topBar_titleTextSize, 0);
    titleColor = ta.getColor(R.styleable.topBar_titleColor, 0);
    titleBackground = ta.getDrawable(R.styleable.topBar_titleBackground);


    leftText = ta.getString(R.styleable.topBar_leftText);
    leftTextColor = ta.getColor(R.styleable.topBar_leftTextColor, 0);
    leftTextSize = (int) ta.getDimension(R.styleable.topBar_leftTextSize, 0);
    leftBackground = ta.getDrawable(R.styleable.topBar_leftBackground);


    rightText = ta.getString(R.styleable.topBar_rightText);
    rightTextColor = ta.getColor(R.styleable.topBar_rightTextColor, 0);
    rightTextSize = (int) ta.getDimension(R.styleable.topBar_rightTextSize, 0);
    rightBackground = ta.getDrawable(R.styleable.topBar_rightBackground);


    ta.recycle();//手动回收ta

}


/**
 * @param context
 * @param attrs
 * @return void
 * <p/>
 * 将自定义的属性与组件关联
 */
private void relevanceView(Context context, AttributeSet attrs) {


    leftButton = new Button(context);
    rightButton = new Button(context);
    titleTextView = new TextView(context);


    titleTextView.setText(titleText);
    titleTextView.setTextSize(titleTextSize);
    titleTextView.setTextColor(titleColor);
    titleTextView.setBackground(titleBackground);
    titleTextView.setGravity(Gravity.CENTER);


    leftButton.setText(leftText);
    leftButton.setTextColor(leftTextColor);
    leftButton.setTextSize(leftTextSize);
    leftButton.setBackground(leftBackground);


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

    setBackgroundColor(0x59563);

    //设置leftButtonwidthheight
    leftLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    //leftButton居左对齐
    leftLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);

    this.addView(leftButton, leftLayoutParams);


    //设置rightButtonwidthheight

    rightLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    //使rightButton居右对齐
    rightLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);
    this.addView(rightButton, rightLayoutParams);

    //设置titlewidthheight

    titleLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.MATCH_PARENT);

    //使titleTextView居中对齐
    titleLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, TRUE);
    this.addView(titleTextView, titleLayoutParams);


}

   4)运用接口回调机制,提供事件监听  

/**
 * 该接口用于外部点击事件
 */
public interface TopBarClickListener {


    public void setLeftOnClickListener();

    public void setRightOnClickListener();

}
/**
 * @param listener
 * @return void
 * 将接口暴露给外部,提供外部访问
 */
public void setOnClickListener(TopBarClickListener listener) {
    this.listener = listener;
}

/**
 * @param
 * @return void
 * <p/>
 * 设置接口回调
 */
private void topBarClickListener() {


    leftButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {


            listener.setLeftOnClickListener();

        }
    });


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


        }
    });

}


5)设置左右Button是否显示

/**
 * @param leftVisibility
 * @param rightVisibility
 * @return void
 * 设置左右Button是否显示
 */
public void setVisibility(boolean leftVisibility, boolean rightVisibility) {

    if (!leftVisibility && !rightVisibility) {
        leftButton.setVisibility(GONE);
        rightButton.setVisibility(GONE);
    } else if (leftVisibility && !rightVisibility) {
        leftButton.setVisibility(VISIBLE);
        rightButton.setVisibility(GONE);

    } else if (!leftVisibility && rightVisibility) {
        leftButton.setVisibility(GONE);
        rightButton.setVisibility(VISIBLE);

    } else {
        leftButton.setVisibility(VISIBLE);
        rightButton.setVisibility(VISIBLE);
    }

}

6)在activity_content的xml文布局该自定义的组件


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"
    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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">


    <com.yongxiang.sm.customview.TopBar
        android:id="@+id/top"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        custom:leftBackground="#e78df2"
        custom:leftText="back"
        custom:leftTextColor="#FFFFFF"
        custom:leftTextSize="12sp"
        custom:rightBackground="#e78df2"
        custom:rightText="more"
        custom:rightTextColor="#FFFFFF"
        custom:rightTextSize="12sp"
        custom:titleBackground="#64f2a0"
        custom:titleColor="#456321"
        custom:titleText="title"
        custom:titleTextSize="16sp"


        ></com.yongxiang.sm.customview.TopBar>


</RelativeLayout>


7)在Activity中运用

public class MainActivity extends AppCompatActivity {


    private TopBar topBar;

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

        initView();
        initEvent();
        initVisiblity();

    }


    /**
     * @param
     * @return void
     * 初始化组件
     */

    private void initView() {

        this.topBar = (TopBar) findViewById(R.id.top);
    }

    /**
     * @param
     * @return void
     * <p/>
     * 初始化事件监听
     */
    private void initEvent() {

        this.topBar.setOnClickListener(new TopBar.TopBarClickListener() {
            @Override
            public void setLeftOnClickListener() {
                Toast.makeText(MainActivity.this, "left Button OnClick!", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void setRightOnClickListener() {
                Toast.makeText(MainActivity.this, "right Button OnClick!", Toast.LENGTH_SHORT).show();

            }
        });
    }


    /**
     * @param
     * @return void
     * <p/>
     * 设置左右Button是否显示
     */
    private void initVisiblity() {

        topBar.setVisibility(true, true);

    }


}



ps:以上源代码可以粘贴到module运行看其效果




    

    

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值