由于强迫症,想不完整定义自定义单选布局对话框就用setSingleChoiceItems实现,于是进行了一些研究,
经过appcompat包源码分析,AlertController类使用了主题,
构造函数中
![](https://i-blog.csdnimg.cn/blog_migrate/bbd1793f39960976bb96f544875d0384.png)
75769474936c8bf569d5e971b2fc0fe.jpg
this.mSingleChoiceItemLayout = a.getResourceId(styleable.AlertDialog_singleChoiceItemLayout, 0);
<style name="Base.AlertDialog.AppCompat" parent="android:Widget">
<item name="android:layout">@layout/abc_alert_dialog_material</item>
<item name="listLayout">@layout/abc_select_dialog_material</item>
<item name="listItemLayout">@layout/select_dialog_item_material</item>
<item name="multiChoiceItemLayout">@layout/select_dialog_multichoice_material</item>
<item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_material</item>
<item name="buttonIconDimen">@dimen/abc_alert_dialog_button_dimen</item>
</style>
单选对话框默认使用的是select_dialog_singlechoice_material
进一步分析,发现根布局判断是否是checkable,如果改用普通view,则无法实现check效果,因此我用跟布局实现checkable,然后代理事件转发给子viewCheckedTextView
实现了转发选中事件的逻辑。
关于check的逻辑,在AbsListView.updateOnScreenCheckedViews
有实现,
关于 如何找到textview以及修改怎么获取文本内容 的呢?
实际上是根据adapter的构造函数传递textViewResourceId
实现的,因此构造函数进行了一下调整,
而获取文本内容使用的是泛型类的toString()
,所以toString()
直接返回标题
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Checkable;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.sotrun.app.R;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ColorSelectAdapter extends ArrayAdapter<ColorSelectAdapter.Bean> {
public ColorSelectAdapter(@NonNull Context context, int resource) {
super(context, resource, android.R.id.text1);
}
public ColorSelectAdapter(@NonNull Context context, int resource, int textViewResourceId) {
this(context, resource, textViewResourceId, new ArrayList<>());
}
public ColorSelectAdapter(@NonNull Context context, int resource, @NonNull Bean[] objects) {
this(context, resource, android.R.id.text1, Arrays.asList(objects));
}
public ColorSelectAdapter(@NonNull Context context, int resource, int textViewResourceId, @NonNull Bean[] objects) {
this(context, resource, textViewResourceId, Arrays.asList(objects));
}
public ColorSelectAdapter(@NonNull Context context, int resource, @NonNull List<Bean> objects) {
this(context, resource, android.R.id.text1, objects);
}
public ColorSelectAdapter(@NonNull Context context, int resource, int textViewResourceId, @NonNull List<Bean> objects) {
super(context, resource, textViewResourceId, objects);
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view = super.getView(position, convertView, parent);
if (view instanceof CheckableProxyView) {
} else {
ViewGroup temp = new CheckableProxyView(getContext());
temp.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT));
temp.addView(view);
view = temp;
}
CheckableProxyView checkableProxyView = (CheckableProxyView) view;
Checkable tvTitle = view.findViewById(android.R.id.text1);
checkableProxyView.setCheckNotify(new CheckableProxyView.CheckNotify() {
@Override
public void setChecked(boolean checked) {
tvTitle.setChecked(checked);
}
@Override
public boolean isChecked() {
return tvTitle.isChecked();
}
@Override
public void toggle() {
tvTitle.toggle();
}
});
Bean item = getItem(position);
View viewColor = view.findViewById(R.id.view_color);
viewColor.setBackgroundColor(getContext().getResources().getColor(item.color));
return view;
}
public static class CheckableProxyView extends FrameLayout implements Checkable {
public CheckableProxyView(Context context) {
super(context);
}
public CheckableProxyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public CheckableProxyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CheckableProxyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void setChecked(boolean checked) {
if (checkNotify != null) {
checkNotify.setChecked(checked);
}
}
@Override
public boolean isChecked() {
if (checkNotify != null) {
return checkNotify.isChecked();
}
return false;
}
@Override
public void toggle() {
if (checkNotify != null) {
checkNotify.toggle();
}
}
public void setCheckNotify(CheckNotify checkNotify) {
this.checkNotify = checkNotify;
}
CheckNotify checkNotify;
interface CheckNotify {
void setChecked(boolean checked);
boolean isChecked();
void toggle();
}
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public long getItemId(int position) {
return position;
}
public static class Bean {
public int color;
public String title;
@Override
public String toString() {
return title;
}
}
}
对话框的逻辑
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
int currentMode = NightModeUtils.Companion.getSpfThemeMode(AppContext.getInstance());
ThemeMode[] values = ThemeMode.values();
ColorSelectAdapter.Bean[] items=new ColorSelectAdapter.Bean[values.length];
for (int i = 0; i < values.length; i++) {
String title = AppContext.getInstance().getString(values[i].getStringValueId());
ColorSelectAdapter.Bean bean=new ColorSelectAdapter.Bean();
bean.title=title;
bean.color=values[i].getColor();
items[i]=bean;
}
ColorSelectAdapter arrayAdapter = new ColorSelectAdapter(
getActivity(), R.layout.view_color_check_item, items);
builder.setSingleChoiceItems(arrayAdapter, currentMode, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which != currentMode) {
dialog.dismiss();
ThemeMode value = values[which];
NightModeUtils.getInstance(AppContext.getInstance()).setThemeMode(value);
EventBus.getDefault().post(new ThemeChangeEvent().themeChange());
}
}
});
builder.setTitle(AppContext.getStr(R.string.deep_color_theme_setting));
builder.show();
view_color_check_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<View
android:layout_margin="10dp"
android:layout_marginRight="0dp"
android:id="@+id/view_color"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_vertical" />
<CheckedTextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:drawableStart="?android:attr/listChoiceIndicatorSingle"
android:drawableLeft="?android:attr/listChoiceIndicatorSingle"
android:drawablePadding="20dp"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:minHeight="?attr/listPreferredItemHeightSmall"
android:paddingStart="@dimen/abc_select_dialog_padding_start_material"
android:paddingLeft="@dimen/abc_select_dialog_padding_start_material"
android:paddingEnd="?attr/dialogPreferredPadding"
android:paddingRight="?attr/dialogPreferredPadding"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?attr/textColorAlertDialogListItem" />
</LinearLayout>