Android 自定义控件:组合控件

自定义组合控件就是多个控件组合起来成为一个新的控件,用来解决多次重复的使用同一类型的布局,比如对话框、APP的标题栏等。这里列举一个最近项目开发中自定义的组合控件。

先看做好的效果:

自定义的选择按钮

按钮选中的样式:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="3dp" />
    <solid android:color="@color/white" />
    <stroke
        android:width="1dp"
        android:color="#2d6fff" />
</shape>

按钮未选中时候的样式:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="3dp" />
    <solid android:color="@color/white" />
    <stroke
        android:width="1dp"
        android:color="#dcdcdc" />
</shape>

样式布局:

右下角的打钩样式以及文字提示

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/mImg"
        android:layout_width="15dp"
        android:layout_height="15dp"
        android:scaleType="fitXY"
        android:src="@drawable/selected_radio"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <TextView
        android:id="@+id/mTv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

自定义属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MarkRadioButton">
        <attr name="textSize" format="integer" />
        <attr name="text" format="string"/>
    </declare-styleable>
</resources>

具体实现:

package cn.zzw.composeview.custom.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;

import cn.zzw.composeview.R;

/**
 * @author 鹭岛猥琐男
 * @create 2019/10/2 22:59
 */
public class MarkRadioButton extends LinearLayout {
    private boolean checked;
    private TextView mTv;
    private ImageView mImg;
    private View mRootView;
    private Drawable mDrawableUnChecked;
    private Drawable mDrawableChecked;


    public MarkRadioButton(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        initView(context);
        /* 获取自定义的属性*/
        TypedArray typedArray = getContext()
                .obtainStyledAttributes(attrs, R.styleable.MarkRadioButton);
        if (null != typedArray) {
            int textSize = typedArray.getInt(R.styleable.MarkRadioButton_textSize, 0);
            String text = typedArray.getString(R.styleable.MarkRadioButton_text);
            mTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
            mTv.setText(text);
        }
    }

    private void initView(Context context) {
        mRootView = LayoutInflater.from(getContext()).inflate
                (R.layout.layout_mark_radiobutton, this);
        mTv = mRootView.findViewById(R.id.mTv);
        mImg = mRootView.findViewById(R.id.mImg);
        mDrawableUnChecked = context.getResources().getDrawable
                (R.drawable.bg_mark_radiobutton_unchecked);
        mDrawableChecked = context.getResources().getDrawable
                (R.drawable.bg_mark_radiobutton_checked);
    }

    /**
     * 设置选择状态
     */
    public void setChecked(boolean checked) {
        this.checked = checked;
        if (this.checked) {
            mImg.setVisibility(VISIBLE);
            mRootView.setBackground(mDrawableChecked);
            mTv.setTextColor(Color.parseColor("#2d6fff"));
        } else {
            mTv.setTextColor(Color.parseColor("#666666"));
            mImg.setVisibility(GONE);
            mRootView.setBackground(mDrawableUnChecked);
        }
        invalidate();
    }

}

 自定义对话框实现:

自定义对话框的风格:

    <!-- Dialog -->
    <style name="base_dialog" parent="android:Theme.Dialog">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowCloseOnTouchOutside">true</item>
    </style>

对话框的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/dialog_bg"
    android:splitMotionEvents="false"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="327dp"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="43dp"
            android:gravity="center"
            android:text="性别选择"
            android:textColor="#444444"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#dddddd" />

        <TextView
            android:id="@+id/mMsg_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginTop="12dp"
            android:text="请选择性别"
            android:textColor="#8E8D8D"
            android:textSize="16sp" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="5dp"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_horizontal"
            >

            <cn.zzw.composeview.custom.view.MarkRadioButton
                android:id="@+id/mRbLeft"
                android:layout_width="132dp"
                android:layout_height="50dp"
                app:text="男"
                app:textSize="16"></cn.zzw.composeview.custom.view.MarkRadioButton>

            <TextView
                android:layout_width="31dp"
                android:layout_height="wrap_content"/>

            <cn.zzw.composeview.custom.view.MarkRadioButton
                android:id="@+id/mRbRight"
                android:layout_width="132dp"
                android:layout_height="50dp"
                app:text="女"
                app:textSize="16"></cn.zzw.composeview.custom.view.MarkRadioButton>

        </LinearLayout>

        <TextView
            android:layout_width="29dp"
            android:layout_height="29dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#dddddd" />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:layout_gravity="bottom"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/mBtnCancel"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:textSize="16sp"
                android:gravity="center"
                android:text="取消"
                android:textColor="#8E8D8D"
                android:layout_height="match_parent"/>

            <TextView
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:background="#dddddd"/>

            <TextView
                android:id="@+id/mBtnConfirm"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:textSize="16sp"
                android:gravity="center"
                android:text="确定"
                android:textColor="#F15E61"
                android:layout_height="match_parent"/>
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

对话框的实现:

package cn.zzw.composeview.custom.dialog;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;

import androidx.annotation.NonNull;

import cn.zzw.composeview.R;
import cn.zzw.composeview.custom.view.MarkRadioButton;

/**
 * @author 鹭岛猥琐男
 * @create 2019/10/2 23:09
 */
public class SelectDialog extends Dialog implements
        View.OnClickListener, DialogInterface.OnDismissListener {
    private MarkRadioButton mRbLeft;
    private MarkRadioButton mRbRight;
    private View mBtnCancel;
    private View mBtnConfirm;
    private int mCheckedIndex;// 在点击确认取消按钮的时候,返回当前选中哪个按钮(从左到右,从0开始)
    private boolean mRbLeftIsChecked = true;
    private boolean mRbRightIsChecked = !mRbLeftIsChecked;
    private IDialogButtonClickListener mListener;

    public SelectDialog(@NonNull Context context) {
        this(context, R.style.base_dialog);
    }

    public SelectDialog(@NonNull Context context, int themeResId) {
        super(context, themeResId);
        init();
    }

    private void init() {
        View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_select,
                null);
        setContentView(view);
        mRbLeft = view.findViewById(R.id.mRbLeft);
        mRbLeft.setChecked(true);
        mRbRight = view.findViewById(R.id.mRbRight);
        mRbRight.setChecked(false);
        mRbLeft.setOnClickListener(this);
        mRbRight.setOnClickListener(this);
        mBtnCancel = view.findViewById(R.id.mBtnCancel);
        mBtnConfirm = view.findViewById(R.id.mBtnConfirm);
        mBtnCancel.setOnClickListener(this);
        mBtnConfirm.setOnClickListener(this);
    }

    public void setOnDialogButtonClickListener(IDialogButtonClickListener listener) {
        this.mListener = listener;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.mRbLeft:
                if (!mRbLeftIsChecked) {
                    mRbLeftIsChecked = true;
                    mRbLeft.setChecked(true);
                    mRbRight.setChecked(!mRbLeftIsChecked);
                    mCheckedIndex = 0;
                }
                break;
            case R.id.mRbRight:
                if (mRbLeftIsChecked) {
                    mRbLeftIsChecked = false;
                    mRbLeft.setChecked(false);
                    mRbRight.setChecked(!mRbLeftIsChecked);
                    mCheckedIndex = 1;
                }
                break;
            case R.id.mBtnCancel:
                if (null != mListener) {
                    mListener.leftButtonClick(mCheckedIndex);
                }
                dismiss();
                break;
            case R.id.mBtnConfirm:
                if (null != mListener) {
                    mListener.RightButtonClick(mCheckedIndex);
                }
                dismiss();
                break;
        }
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        if (mListener != null) {
            mListener.onDialogDissmiss();
        }
    }

    /* 对话框的接口*/
    public interface IDialogButtonClickListener {
        void leftButtonClick(int mCheckedIndex);

        void onDialogDissmiss();

        void RightButtonClick(int mCheckedIndex);
    }
}

调用对话框:

package cn.zzw.composeview;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import cn.zzw.composeview.custom.dialog.SelectDialog;

public class MainActivity extends AppCompatActivity implements SelectDialog.IDialogButtonClickListener {
    private SelectDialog mDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.mBtnDialog).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (null == mDialog) {
                    mDialog = new SelectDialog(MainActivity.this);
                    mDialog.setOnDialogButtonClickListener(MainActivity.this);
                }
                if (!mDialog.isShowing()) {
                    mDialog.show();
                }
            }
        });
    }

    @Override
    public void leftButtonClick(int mCheckedIndex) {
        Toast.makeText(this, "选中按钮的下标: " + mCheckedIndex, Toast.LENGTH_SHORT).show();
        mDialog = null;
    }

    @Override
    public void onDialogDissmiss() {
        mDialog = null;
    }

    @Override
    public void RightButtonClick(int mCheckedIndex) {
        Toast.makeText(this, "选中按钮的下标: " + mCheckedIndex, Toast.LENGTH_SHORT).show();
        mDialog = null;
    }
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值