前言:
好吧,这里我就吐槽一下在制作的过程中最大的迷惑吧,因为 我个人使用的是华为手机作为真机来来调试的,然后等我实现好我的逻辑 一上真机就发现了一个问题,为啥我的dialog样式跟我的设计相差那么大的变化,这这这太奇怪了吧,然后开始找错误了,到最后才发现,原来我继承的 AlertDialog 在 华为 和 小米手机上样式已经遭到了更改。一把父类更改为 Dialog 就恢复会正常的状态。
还有里面涉及到一点就是使用到 checkBox 如果我们没有一开始为checkbox设置 id 还有设置他的 选择状态。不然就会造成错位。
本文案例的需求:
实现 dialog 里面带有Recylerview ,Recylerview 里面的 item 带有一个选择框(可实现单选或多选的功能)
效果图:
通过本文你可以学到以下几个方面
(注意以下代码例子均为个人案例)
- 知道自定义控件的三种方式
- 懂得在设计前先进行分析
- 懂得 Dialog 如何继承原生控件来进行扩展
Android 自定义控件的三种实现方式
- 组合原生控件
- 自己绘制
- 继承原生控件
而在这里我们是使用的是第三种方式来作为实现 继承原生控件 来自定义控件
自定义前的分析
1、dialog 里面带有 Recylerview 控件,一般我们都为 Recylerview 的 item 设置一个点击事件,所以这里我们要先实现一个接口,就可以用组合的方式来实现回调。
在 Recylerview 的 Adapter 实现一个接口
public interface OnItemClickListener {
void onItemClick(int position);
}
2、dialog 里面固定模式带有 确定 和 取消 两个控件,这里我们就可以如上面一点一样在 dialog 里面实现一个接口,以作为回调。第一个方法就靠我们对我们项目的自我分析了,因为在我们的项目当中,当我点击 确定 控件的时候,我就会把我们 Recylerview 所选择的数据回调给界面。
public interface OnSelectorListener {
void getSelectorData(List<DialogMemberBean> trees);
void cancel();
}
3、一般我们都是为了我们代码的可读性,我们在创建的 dialog 的时候,都会这个 自定义控件 多添加一个 帮助类,如我我就添加了一个 dialoghelp 类。所以此时我们为了把我们的 数据回调到前台 那我们就还需要在这个帮助类里面同样的创建一个 接口,来作为回调。就是当dialog类回调 数据 给 Helper类 的时候在,我们在Helper类在把这数据回调给前台。
public interface OnHelperSelectorListener {
void getSelectorPosition(List<DialogMemberBean> trees);
}
分析完我们开始我们的实现
1、先制作我们的dialog样式
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_selector"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_bottom_line"
android:layout_width="match_parent"
android:layout_height="@dimen/leave_line_height"
android:layout_above="@+id/ll_bottom_btn"
android:background="@color/leave_add_line" />
<LinearLayout
android:id="@+id/ll_bottom_btn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button
android:id="@+id/btn_cancel"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/refer_tree_cancel_btn"
android:text="@string/cancel"
android:textColor="#000" />
<Button
android:id="@+id/btn_ok"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#feaa25"
android:text="@string/sure"
android:textColor="@color/white" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
2、实现 dialog 中 Recylerview 的 item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rl_branch_item_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_margin="4dp"
android:layout_marginLeft="10dp"
android:text="姓名"
android:textColor="@color/common_personInfo_text_bg"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_name"
android:layout_centerVertical="true"
android:layout_margin="4dp"
android:layout_marginLeft="10dp"
android:text="工号"
android:textColor="@color/common_personInfo_text_bg"
android:textSize="12sp" />
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<CheckBox
android:id="@+id/box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginRight="8dp"/>
</LinearLayout>
<include layout="@layout/include_common_split_line_hor" />
</LinearLayout>
界面制作结束,我们就按照我们分析的步骤来实现 java 类
adapter类
package com.example.jie.sign.Adapter;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.TextView;
import com.example.jie.sign.Bean.DialogMemberBean;
import com.example.jie.sign.R;
import java.util.List;
/**
* Created by jie on 2018/9/9.
*/
public class DialogMemberAdapter extends RecyclerView.Adapter<DialogMemberAdapter.ViewHolder> {
private List<DialogMemberBean> list;
private OnItemClickListener mOnItemClickListener;
private ViewHolder mholder;
private final int style;// 0 为 单选模式 1 为 多选模式
static public class ViewHolder extends RecyclerView.ViewHolder {
TextView name;
TextView number;
CheckBox box;
public ViewHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.tv_name);
number = itemView.findViewById(R.id.tv_number);
box = itemView.findViewById(R.id.box);
}
}
/**
* @param list 为数据集
* @param style1 为样式设置
*/
public DialogMemberAdapter(List<DialogMemberBean> list,int style1) {
this.list = list ;
this.style = style1;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_dialog_item, null);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
DialogMemberBean lock = list.get(position);
holder.name.setText(lock.getName());
holder.number.setText(lock.getNumber());
holder.box.setChecked(lock.isSelector());
holder.box.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (style==1){
mOnItemClickListener.onItemClick(position);
}else{
if (mholder==null){
mholder = holder;
}else{
mholder.box.setChecked(false);
mholder = holder;
}
mOnItemClickListener.onItemClick(position);
}
}
});
}
@Override
public int getItemCount() {
return list.size();
}
/**
* @param onItemClickListener 监听设置
*/
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
/**
* 监听回调接口
*/
public interface OnItemClickListener {
void onItemClick(int position);
}
}
DialogSelector 类
package com.example.jie.sign.CustomView;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.StyleRes;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.example.jie.sign.Adapter.DialogMemberAdapter;
import com.example.jie.sign.Bean.DialogMemberBean;
import com.example.jie.sign.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by jie on 2018/9/9.
*/
public class DialogSelector extends Dialog implements DialogMemberAdapter.OnItemClickListener{
private List<DialogMemberBean> DialogMemberBean = new ArrayList<>(); //选择列表的数据
private List<DialogMemberBean> DialogMemberBeanselector = new ArrayList<>();
private Context context;
private OnSelectorListener cdListener;
private DialogMemberAdapter mSelectorBranchAdapter;
private Button btn_cancel;
private Button btn_ok;
private RecyclerView rv_selector_branch;
private int Style; //1 为多选 0 为单选
public DialogSelector(Context context, List<DialogMemberBean> mSimpleListItemEntity,int style1, OnSelectorListener cdListener) {
super(context);
this.context = context;
this.cdListener = cdListener;
this.DialogMemberBean = mSimpleListItemEntity;
this.Style = style1;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.dialog_member);
this.setCanceledOnTouchOutside(false); // 点击外部会消失
InitViews();
}
private void InitViews() {
btn_cancel = findViewById(R.id.btn_cancel);
btn_ok = findViewById(R.id.btn_ok);
rv_selector_branch = (RecyclerView) findViewById(R.id.rv_selector);
btn_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
cdListener.cancel();
}
});
btn_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for (int i = 0; i < DialogMemberBean.size(); i++) {
if (DialogMemberBean.get(i).isSelector()) {
DialogMemberBeanselector.add(DialogMemberBean.get(i));
}
}
cdListener.getSelectorData(DialogMemberBeanselector);
}
});
LinearLayoutManager layoutmanager = new LinearLayoutManager(getContext());
rv_selector_branch.setLayoutManager(layoutmanager);
mSelectorBranchAdapter = new DialogMemberAdapter(DialogMemberBean,Style);
mSelectorBranchAdapter.setOnItemClickListener(this);
rv_selector_branch.setAdapter(mSelectorBranchAdapter);
}
/**
* adpter里面的checkbox监听接口
* @param position item的位置
* 改变元数据集的内容
*/
@Override
public void onItemClick(int position) {
if (Style == 1){
boolean temp = !DialogMemberBean.get(position).isSelector();
DialogMemberBean.get(position).setSelector(temp);
}else{
for (int i = 0; i < DialogMemberBean.size(); i++) {
if (i == position) {
if (!DialogMemberBean.get(i).isSelector()) {
DialogMemberBean.get(i).setSelector(true);
}
} else {
DialogMemberBean.get(i).setSelector(false);
}
}
}
}
/**
* 确定 和 取消控件的回调接口
*/
public interface OnSelectorListener {
void getSelectorData(List<DialogMemberBean> trees);
void cancel();
}
}
Helper 类
package com.example.jie.sign.Utils;
/**
* Created by jie on 2018/9/9.
*/
import android.content.Context;
import com.example.jie.sign.Bean.DialogMemberBean;
import com.example.jie.sign.CustomView.DialogSelector;
import com.example.jie.sign.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by wyy on 2018/1/21.
*/
public class DialogHelper {
private int style;
private static final String TAG = DialogHelper.class.getSimpleName();
private Context context;
private List<DialogMemberBean> DialogMemberBean = new ArrayList<>(); //选择列表的数据
private OnHelperSelectorListener onSelectorListener;
private DialogSelector mDialogSelector;
private DialogHelper(Context context) {
this.context = context;
}
/**
* 初始化
*
* @param context
* @return
*/
public static DialogHelper create(Context context) {
return new DialogHelper(context);
}
/**
* 设置列表的数据
*
* @param contactTreeList
* @return
*/
public DialogHelper setSelectorData(List<DialogMemberBean> contactTreeList) {
this.DialogMemberBean = contactTreeList;
return this;
}
/**
* 设置选择部门监听
*
* @param onSelectorListener
* @return
*/
public DialogHelper setSelectorListener(OnHelperSelectorListener onSelectorListener) {
this.onSelectorListener = onSelectorListener;
return this;
}
/**
* 样式设置
* @param style1
* @return
*/
public DialogHelper setStyle(int style1) {
this.style = style1;
return this;
}
/**
* 弹出弹框
*/
public void showSelectorDialog() {
mDialogSelector = new DialogSelector(context, DialogMemberBean, style, new DialogSelector.OnSelectorListener() {
@Override
public void getSelectorData(List<DialogMemberBean> trees) {
mDialogSelector.dismiss();
onSelectorListener.getSelectorPosition(trees);
}
@Override
public void cancel() {
mDialogSelector.dismiss();
}
});
mDialogSelector.setCancelable(false);
mDialogSelector.show();
}
/**
*监听接口
*/
public interface OnHelperSelectorListener {
void getSelectorPosition(List<DialogMemberBean> trees);
}
}
前台使用
DialogHelper.create(this).setSelectorData(mSimpleListItemEntity).setStyle(1).setSelectorListener(this).showSelectorDialog();
//回调
@Override
public void getSelectorPosition(List<DialogMemberBean> trees) {
Log.e("getSelectorPosition:",String.valueOf(trees));
}
本文所用的数据集
package com.example.jie.sign.Bean;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by jie on 2018/9/9.
*/
public class DialogMemberBean implements Parcelable {
private String name;
private String number;
private boolean isSelector = false;
public boolean isSelector() {
return isSelector;
}
public void setSelector(boolean selector) {
isSelector = selector;
}
public DialogMemberBean(String name, String number) {
this.name = name;
this.number = number;
}
public DialogMemberBean() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
dest.writeString(this.number);
}
protected DialogMemberBean(Parcel in) {
this.name = in.readString();
this.number = in.readString();
}
public static final Parcelable.Creator<DialogMemberBean> CREATOR = new Parcelable.Creator<DialogMemberBean>() {
@Override
public DialogMemberBean createFromParcel(Parcel source) {
return new DialogMemberBean(source);
}
@Override
public DialogMemberBean[] newArray(int size) {
return new DialogMemberBean[size];
}
};
}
Thanks!!!