Android自定义控件之自定义组合控件

简介

在Android开发中,我们经常会遇到需要自定义控件的情况。Android提供了很多基本的控件,但有时候我们需要更加灵活、更加符合业务需求的控件。这时候,我们就需要自定义控件了。自定义控件可以让我们根据自己的需求去实现各种各样的UI效果,从而更好地满足用户的需求。

本文将介绍Android中的自定义组合控件。所谓自定义组合控件,就是将多个基本控件组合在一起,形成一个新的控件,用于实现一些特定的功能。通过自定义组合控件,我们可以将多个控件的功能集成在一个控件中,从而简化代码,提高开发效率。

自定义组合控件的实现方式

Android中实现自定义组合控件有两种方式:继承现有的控件和自定义ViewGroup。

继承现有的控件

这种方式比较简单,我们只需要继承现有的控件,然后在子类中添加其他控件即可。下面是一个示例:

public class CustomButton extends Button {

    private ImageView mIcon;

    public CustomButton(Context context) {
        super(context);
        init();
    }

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public void setIcon(int resId) {
        mIcon.setImageResource(resId);
    }

    private void init() {
        mIcon = new ImageView(getContext());
        mIcon.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        mIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);

        Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher_background);
        mIcon.setImageDrawable(drawable);

        addView(mIcon);
    }
}

在这个例子中,我们继承了Button控件,并添加了一个ImageView控件。我们可以在代码中调用setIcon方法来设置图片。

自定义ViewGroup

这种方式稍微复杂一些,我们需要继承ViewGroup类,并在子类中添加其他控件。下面是一个示例:

public class CustomLayout extends ViewGroup {

    private ImageView mIcon;
    private TextView mText;

    public CustomLayout(Context context) {
        super(context);
        init();
    }

    public CustomLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mIcon = new ImageView(getContext());
        mIcon.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        mIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);

        Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher_background);
        mIcon.setImageDrawable(drawable);

        addView(mIcon);

        mText = new TextView(getContext());
        mText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        mText.setText("Hello World");

        addView(mText);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int width = r - l;
        int height = b - t;

        int iconWidth = mIcon.getMeasuredWidth();
        int iconHeight = mIcon.getMeasuredHeight();
        int iconLeft = (width - iconWidth) / 2;
        int iconTop = (height - iconHeight) / 2;
        mIcon.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);

        int textWidth = mText.getMeasuredWidth();
        int textHeight = mText.getMeasuredHeight();
        int textLeft = (width - textWidth) / 2;
        int textTop = iconTop + iconHeight;
        mText.layout(textLeft, textTop, textLeft + textWidth, textTop + textHeight);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int iconWidth = mIcon.getLayoutParams().width;
        int iconHeight = mIcon.getLayoutParams().height;
        int textWidth = mText.getLayoutParams().width;
        int textHeight = mText.getLayoutParams().height;

        int width;
        int height;

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = Math.max(iconWidth, textWidth