1. 构建一个dialog样式的activity:
作为主题的style:
<style name="dialogutil_dialog_activity_style" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowCloseOnTouchOutside">false</item>
<item name="android:windowIsFloating">true</item>
</style>
注意:windowBackground-如果在原处已设置,此处则无需再有.透明即可.
复杂,不便于序列化的ConfigInfo对象的传入:
不要思维定势,谁说就一定要用intent传入? 利用普通对象依赖注入也是一样可以的:
获取ActivityStack最上层Activity,判断是否为目标activity,如果是,则拿到这个对象,强转后调用其方法即可:
private void showAsActivity(){
Activity activity = ActivityStackManager.getInstance().getTopActivity();
if(activity!=null){
Intent intent = new Intent(activity, DialogUtil_DialogActivity.class);
activity.startActivity(intent);
showViewWhenActivityIsReady();
}
}
private void showViewWhenActivityIsReady() {
Tool.getMainHandler().postDelayed(new Runnable() {
@Override
public void run() {
Activity activity1 = ActivityStackManager.getInstance().getTopActivity(DialogUtil_DialogActivity.class);
if(activity1!=null){
buildByType(ConfigBean.this);//保证构建view的context是DialogUtil_DialogActivity
DialogUtil_DialogActivity activity2 = (DialogUtil_DialogActivity) activity1;
activity2.show(ConfigBean.this);
}else {
showViewWhenActivityIsReady();
}
}
},300);
}
contentview的设置
原先代码全部用于构建dialog,拆分很麻烦,需要用一种巧妙的方式从dialog中提取view然后设置给activity的content,同时,还要兼顾context的一致性(见上方代码注释):
public void show(ConfigBean bean){
this.bean = bean;
View view = null;
if(bean.dialog !=null){
view =bean.dialog.getWindow().getDecorView();
}else if(bean.alertDialog !=null){
view = bean.alertDialog.getWindow().getDecorView();
}
if(view!=null){
setContentView(view);
}else {
finish();
}
}
2.不让AlertDialog一点击按钮就消失:
android的AlertDialog默认一点击按钮就消失,但是有的时候我们需要它不消失,那么可以这样:
builder.setTitle(bean.title)
.setPositiveButton(bean.text1, null)//不让点击默认消失,而是做出判断,见Tool.setMdBtnStytle
//在show之后,或者在globalviewtreeobserver中:
/**
* 必须在show之后,button才不会返回null
* @param bean
*/
public static void setMdBtnStytle(final ConfigBean bean){
Button btnPositive =
bean.alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
Button btnNegative =
bean.alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
Button btnNatural =
bean.alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
if(btnPositive !=null){
btnPositive.setAllCaps(false);
if(!TextUtils.isEmpty(bean.text1)){
btnPositive.setText(bean.text1);
}
if (bean.btn1Color > 0)
btnPositive.setTextColor(getColor(bean.context,bean.btn1Color));
if(bean.btnTxtSize >0){
btnPositive.setTextSize(bean.btnTxtSize);
}
btnPositive.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(bean.type == DefaultConfig.TYPE_MD_INPUT){
MdInputHolder holder = (MdInputHolder) bean.viewHolder;
boolean isvalid = bean.listener.onInputValid(holder.getTxt1(),holder.getTxt2(),holder.getEt1(),holder.getEt2());
if(!isvalid){
return;
}
bean.listener.onGetInput(holder.getTxt1(),holder.getTxt2());
}
bean.listener.onFirst();
Tool.hideKeyBorad(bean);
bean.alertDialog.dismiss();
}
});
}
...
3.listview里设置item的单选多选
item的实现采用CheckedTextView,可以拷贝support包下的select_dialog_multichoice_material.xml的内容
选择状态被listview接管,无法通过CheckedTextView控制.
设置选择模式:
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
初始化选中状态:
//初始化其选择状态
for (int i = 0; i < bean.chooseBeans.size(); i++) {
ChooseBean chooseBean = bean.chooseBeans.get(i);
listView.setItemChecked(i,chooseBean.choosen);
}
设置最终回调获取选择情况:
- 单选:点击一个item就回传选择结果,并关闭对话框,无需确定按钮
//todo 点击一个item即可消失
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(bean.listener !=null){
bean.listener.onGetChoose(position,bean.chooseBeans.get(position).txt);
}
if(bean.itemListener !=null){
bean.itemListener.onItemClick(bean.chooseBeans.get(position).txt,position);
}
Tool.dismiss(bean);
}
});
- 多选: 点击确定按钮后才统计并回传
btnP.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SparseBooleanArray booleanArray = listView.getCheckedItemPositions();
//todo 回传多选结果
List<Integer> selectedIndexs = new ArrayList<>(booleanArray.size());
List<CharSequence> selectStrs = new ArrayList<>(booleanArray.size());
boolean[] states = new boolean[bean.chooseBeans.size()];
for (int i = 0; i < booleanArray.size(); i++) {
Boolean selected = booleanArray.get(i);
if(selected){
selectedIndexs.add(i);
selectStrs.add(bean.chooseBeans.get(i).txt);
}
states[i] = selected;
}
bean.listener.onChoosen(selectedIndexs,selectStrs,states);
Tool.dismiss(bean);
}
});
4. 基于ViewHolder的MVVM模式
原先只为listview的superadapter封装而创建的superviewholder,对一般view也是特别好用.
内部定义两个方法,一个设置layoutid,一个设置数据和事件,确实具有普适性和优良的封装性,而且比官方databinding灵活多了.
public abstract class SuperLvHolder<T> {
public View rootView;
public SuperLvHolder(Context context){
rootView = View.inflate(context,setLayoutRes(),null);
//ButterKnife.bind(this,rootView);
findViews();
}
//这里作为lib不想再依赖其他lib,所以用插件生成findviewbyid. 实际项目直接用上面的Butterknife
protected abstract void findViews();
protected abstract @LayoutRes int setLayoutRes();
/**
* 一般情况下,实现这个方法就足够了
* if use as custom view holder ,the bean will return as null,do not use it
* @param context
* @param bean
*/
public abstract void assingDatasAndEvents(Context context, @Nullable T bean);
/**
* 如果有需要,才实现这个方法
* @param context activity实例,用于一些点击事件
* @param bean 该条目的数据
* @param position 该条目所在的位置
* @param isLast 是否为最后一条,有些情况下需要用到
* @param isListViewFling listview是不是在惯性滑动,备用
* @param datas 整个listview对应的数据
* @param superAdapter adapter对象引用,可用于触发notifydatesetChanged()方法刷新整个listview,比如更改的单选按钮
*/
public void assingDatasAndEvents(Context context, T bean, int position , boolean isLast,
boolean isListViewFling, List datas, SuperLvAdapter superAdapter){
assingDatasAndEvents(context,bean);
}
}
网友评论