android 自定义的AlertDialog强化版
2017-01-18 16:42
197 查看
上一篇文章http://blog.csdn.net/qq_33748378/article/details/54581422#comments介绍了自定义的AlertDialog,在此基础之上,再来看下常用的自定义的AlertDialog。
自定义的itemDialog:
item_dialog布局文件:
MainActivity中代码:
drawable/edit_item_text_bg:
MianActivity中代码:
效果图:
如果需要对editText输入的内容作限制,需要在EditDialog中添加如下代码:
R.layout.layout_load_progress_dialog为:
实现的效果:
在此基础之上,可以进一步添加自定义样式:
在LoadProgressDialog中改变的代码:
解决的办法是:
完整的项目源码:http://download.csdn.net/detail/qq_33748378/9740725
包含的内容:
ItemDialog:
首先来看下android原生的itemDialogpackage com.example.yk.dialogtest; import android.content.DialogInterface; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.Toast; public class ItemDialogActivity extends AppCompatActivity { private String[] items={"a","b","c","d","e","d","f","g","h","i","j","k","l","m"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_item_dialog); AlertDialog.Builder alertDialog=new AlertDialog.Builder(this); alertDialog.setTitle("title"); alertDialog.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { Toast.makeText(ItemDialogActivity.this, "点击了"+items[i], Toast.LENGTH_SHORT).show(); } }); alertDialog.show(); } }效果如图:
自定义的itemDialog:
package com.example.yk.dialogtest; import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; /** * Created by yk on 2017/1/17. */ public class itemDialog extends Dialog implements AdapterView.OnItemClickListener { public interface OnDialogItemClickListener { /** * 点击item 事件的回调方法 * @param requestCode 用于区分某种情况下的showDialog * @param position * @param item */ void onDialogItemClick(int requestCode, int position,String item); } private String title; private Context context; private String[] items; private int requestCode; private OnDialogItemClickListener listener; public itemDialog(Context context, String title, String[] items, int requestCode, OnDialogItemClickListener listener) { super(context, R.style.MyDialog); this.context=context; this.title=title; this.items=items; this.requestCode=requestCode; this.listener=listener; } private TextView textView; private ListView listView; private ArrayAdapter<String> adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.item_dialog); textView = (TextView) findViewById(R.id.tvItemDialogTitle); listView = (ListView) findViewById(R.id.lvItemDialog); adapter = new ArrayAdapter<String>(context, R.layout.item_dialog_activity,R.id.text_view, items); textView.setText(title); listView.setAdapter(adapter); listView.setOnItemClickListener(this); } @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { listener.onDialogItemClick(requestCode,i, adapter.getItem(i)); dismiss(); } }
item_dialog布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_margin="30dp" android:background="@drawable/edit_item_text_bg" android:layout_height="match_parent"> <TextView android:id="@+id/tvItemDialogTitle" android:textColor="@color/black" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:textSize="21sp" android:layout_margin="15dp" android:text="Title" /> <ListView android:id="@+id/lvItemDialog" android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@color/gray_4" android:dividerHeight="1px" /> </LinearLayout>MyDialog style:
<style name="MyDialog"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowFrame">@null</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsFloating">true</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item> <item name="android:backgroundDimEnabled">true</item> </style>item_dialog_activity布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="40dp" android:padding="10dp" android:id="@+id/text_view" android:gravity="center"/> </LinearLayout>
MainActivity中代码:
package com.example.yk.dialogtest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Toast; public class CustomItemDialog extends AppCompatActivity implements itemDialog.OnDialogItemClickListener { private static final int REQUEST_CODE_SECOND = 2; private String[] items={"a","b","c","d","e","d","f","g","h","i","j","k","l","m"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_item_dialog); itemDialog itemDialog=new itemDialog(this,"title",items,REQUEST_CODE_SECOND,this); itemDialog.show(); } @Override public void onDialogItemClick(int requestCode, int position, String item) { if(requestCode==REQUEST_CODE_SECOND){ Toast.makeText(this, item, Toast.LENGTH_SHORT).show(); } } }效果图:
EditDialog:
editDialog中代码:package com.example.yk.dialogtest; import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.TextView; /** * Created by yk on 2017/1/18. */ public class EditDialog extends Dialog implements View.OnClickListener { public interface OnDialogButtonClickListener{ void onDialogButtonClick(int requestCode,boolean isPositiveBtn,String s); } private String title; private String strPositive; private String strNegative; private int requestCode; private Context context; private OnDialogButtonClickListener listener; public EditDialog(Context context,String title,String strNegative,String strPositive,int requestCode,OnDialogButtonClickListener listener) { super(context,R.style.MyDialog); this.context=context; this.title=title; this.strNegative=strNegative; this.strPositive=strPositive; this.requestCode=requestCode; this.listener=listener; } private TextView tvTitle,tvCancel,tvConfirm; private EditText etInput; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_edit_dialog); tvTitle= (TextView) findViewById(R.id.tv_title); tvCancel= (TextView) findViewById(R.id.tv_cancel); tvConfirm= (TextView) findViewById(R.id.tv_confirm); etInput= (EditText) findViewById(R.id.edit_text); tvTitle.setText(title); if(TextUtils.isEmpty(tvConfirm.getText().toString().trim())){ tvCancel.setVisibility(View.GONE); }else { tvCancel.setVisibility(View.VISIBLE); } tvCancel.setOnClickListener(this); tvConfirm.setOnClickListener(this); tvTitle.postDelayed(new Runnable() { @Override public void run() { showSoftKeyBoard();//弹出输入键盘 } },100); } public void showSoftKeyBoard(){ InputMethodManager manager= (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); manager.toggleSoftInput(0,InputMethodManager.HIDE_NOT_ALWAYS); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.tv_confirm: //点击确定按钮 listener.onDialogButtonClick(requestCode,true,etInput.getText().toString().trim()); break; case R.id.tv_cancel: //点击取消按钮 listener.onDialogButtonClick(requestCode,false,null); break; } dismiss(); } }layout_edit_dialog布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="250dp" android:layout_height="wrap_content" android:layout_margin="50dp" android:background="@drawable/edit_item_text_bg" android:orientation="vertical"> <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="title" android:gravity="center" android:textSize="28sp" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:paddingTop="3dp" android:paddingBottom="3dp" android:textAllCaps="false"/> <EditText android:id="@+id/edit_text" android:singleLine="true" android:inputType="numberDecimal" android:textSize="25sp" android:paddingTop="3dp" android:paddingBottom="3dp" android:layout_marginBottom="5dp" android:layout_width="match_parent" android:layout_height="wrap_content"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tv_cancel" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="取消" android:background="@drawable/bg_item_to_alpha" android:textSize="20sp"/> <View android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/gray_3"/> <TextView android:id="@+id/tv_confirm" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="确定" android:textColor="@color/black" android:textSize="20sp"/> </LinearLayout> </LinearLayout>drawable/bg_item_to_alpha:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/alpha_1" android:state_pressed="true"/> <item android:drawable="@color/alpha_1" android:state_focused="true"/> </selector>
drawable/edit_item_text_bg:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <!--定义填充颜色--> <solid android:color="#ffffff"/> <!--定义四个角的圆角半径--> <corners android:radius="2dp"/> </shape>
MianActivity中代码:
package com.example.yk.dialogtest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Toast; public class EditDialogActivity extends AppCompatActivity implements EditDialog.OnDialogButtonClickListener { private static final int REQUEST_CODE_THIRD = 3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit_dialog); EditDialog editDialog=new EditDialog(this,"title","取消","确定",REQUEST_CODE_THIRD,this); editDialog.show(); } @Override public void onDialogButtonClick(int requestCode, boolean isPositiveBtn, String s) { if(requestCode==REQUEST_CODE_THIRD){ if(isPositiveBtn){ Toast.makeText(this, "输入的内容:"+s, Toast.LENGTH_SHORT).show(); }else { Toast.makeText(this, "点击了取消", Toast.LENGTH_SHORT).show(); } } } }
效果图:
如果需要对editText输入的内容作限制,需要在EditDialog中添加如下代码:
CustomWatcher customWatcher=new CustomWatcher(); etInput.addTextChangedListener(customWatcher);CustomWatcher:
private class CustomWatcher implements TextWatcher { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void afterTextChanged(Editable editable) { String s = editable.toString(); /** * 不以小数点开头 */ if(s.length() ==1 && s.contains(".")){ editable.delete(0,1); return; } /** * 不能以00开头 */ if(s.startsWith("00")){ editable.delete(1,2); return; } /** * 整数部分最长为8位 */ if(!s.contains(".")){ if(s.length() == 9){ editable.delete(8,9); } return; } /** * 小数部分最多有2位 */ if(s.contains(".")){ int start = s.indexOf("." )+ 1; int end=s.length(); if(end-start>2){ editable.delete(start+2,s.length()); } return; } } }效果截图:
LoadProgressDialog:
LoadProgressDialog中代码:package com.example.yk.dialogtest; import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.widget.TextView; /** * Created by yk on 2017/1/18. */ public class LoadProgressDialog extends Dialog{ private String message; private boolean canCancel; public LoadProgressDialog(Context context,String message,boolean canCancel) { super(context); this.message=message; this.canCancel=canCancel; } private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_load_progress_dialog); textView= (TextView) findViewById(R.id.tv_message); setCancelable(canCancel); textView.setText(message); } }MainActivty中代码:
package com.example.yk.dialogtest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class LoadProgressActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_load_progress); LoadProgressDialog dialog=new LoadProgressDialog(this,"加载中",true); dialog.show(); } }
R.layout.layout_load_progress_dialog为:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="280dp" android:layout_height="wrap_content" android:background="@drawable/edit_item_text_bg" android:orientation="vertical"> <TextView android:id="@+id/tv_message" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_marginTop="5dp" android:layout_marginBottom="20dp" android:textSize="20sp"/> <ProgressBar android:id="@+id/progress_bar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"/> </LinearLayout>
实现的效果:
在此基础之上,可以进一步添加自定义样式:
在LoadProgressDialog中改变的代码:
public LoadProgressDialog(Context context,String message,boolean canCancel) { super(context,R.style.easy_dialog_style); this.message=message; this.canCancel=canCancel; }自定义样式R.style.easy_dialog_style为:
<style name="easy_dialog_style" parent="@android:style/Theme.Dialog"> <item name="android:windowFrame">@null</item> <!-- 边框 --> <item name="android:windowIsFloating">true</item> <!-- 是否浮现在activity之上 --> <item name="android:windowIsTranslucent">true</item> <!-- 半透明 --> <item name="android:windowNoTitle">true</item> <!-- 无标题 --> <item name="android:windowBackground">@color/transparent</item> <!-- 背景透明 --> <item name="android:backgroundDimEnabled">true</item> <!-- 后面的activity变暗 --> </style>R.layout.layout_load_progress_dialog布局为:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="280dp" android:layout_height="wrap_content" android:background="@drawable/edit_item_text_bg" android:orientation="vertical"> <TextView android:id="@+id/tv_message" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_marginTop="5dp" android:layout_marginBottom="20dp" android:textSize="20sp"/> <ProgressBar android:id="@+id/progress_bar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingBottom="10dp" android:layout_gravity="center" android:indeterminateDrawable="@drawable/custom_progress_style"/> </LinearLayout>drawable/custom_progress_style:
<?xml version="1.0" encoding="utf-8"?> <animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@mipmap/load_dialog" android:pivotX="50%" android:pivotY="50%" />效果:
控制LoadProgressDialog显示与不显示的工具类:
LoadProgressActivity中代码:package com.example.yk.dialogtest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class LoadProgressActivity extends AppCompatActivity { private LoadProgressDialog dialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_load_progress); // dialog = new LoadProgressDialog(this,"加载中",true); // dialog.show(); LoadProgressUtil.showLoadProgressDialog(this,"加载中",true); } }LoadProgressUtil中代码:
package com.example.yk.dialogtest; import android.content.Context; import android.util.Log; /** * Created by yk on 2017/1/18. */ public class LoadProgressUtil { private static LoadProgressDialog loadProgressDialog; public static void showLoadProgressDialog(Context context,String title, boolean canCancel){ if(loadProgressDialog == null){ loadProgressDialog=new LoadProgressDialog(context,title,canCancel); }else { if(loadProgressDialog.isShowing()){ return; } } // Log.e("context",context.toString()); // Log.e("loadProgressDialog",loadProgressDialog.getContext().toString()); loadProgressDialog.show(); } public static void cancelProgressDialog(){ if(loadProgressDialog==null){ return; }else { if(loadProgressDialog.isShowing()){ loadProgressDialog.dismiss(); }else { return; } } } public static void progressDialogIsShow(){ loadProgressDialog.isShowing(); } }如果像上面这样写的话,会发现,在第一次取消progressDialog,并且退出当前progressDialog所在的Activity,当第二次进入该progressDialog所在的Activity时是会报错的,错误原因:
Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@3d4e7354 is not valid; is your activity running?查阅资料发现,对于AlertDialog来说,是需要依赖一个View,而View是对应于Activity的。那么为什么会报错呢,这里涉及到一个生命周期的问题了。静态变量private static LoadProgressDialog loadProgressDialog;需要等到系统GC的时候才会回收,第二次进入该activity时,此时的context是新的地址,而此时的progress Dialog的context还是上次的activity的,见下图:
解决的办法是:
package com.example.yk.dialogtest; import android.content.Context; import android.util.Log; /** * Created by yk on 2017/1/18. */ public class LoadProgressUtil { private static LoadProgressDialog loadProgressDialog; public static void showLoadProgressDialog(Context context,String title, boolean canCancel){ if(loadProgressDialog == null){ loadProgressDialog=new LoadProgressDialog(context,title,canCancel); }else if(loadProgressDialog.getContext() !=context){ cancelProgressDialog(); loadProgressDialog=new LoadProgressDialog(context,title,canCancel); } // Log.e("context",context.toString()); // Log.e("loadProgressDialog",loadProgressDialog.getContext().toString()); loadProgressDialog.show(); } public static void cancelProgressDialog(){ if(loadProgressDialog==null){ return; }else { if(loadProgressDialog.isShowing()){ loadProgressDialog.dismiss(); loadProgressDialog=null; } } } public static boolean progressDialogIsShow(){ return (loadProgressDialog !=null && loadProgressDialog.isShowing()); } }
完整的项目源码:http://download.csdn.net/detail/qq_33748378/9740725
包含的内容:
相关文章推荐
- 自定义android 系统映像与皮肤,并运行
- Study on Android【五】--自定义ContentProvider的语义
- Android教程之如何使用自定义字体
- 美化你的android程序:自定义ListView背景
- (转)自定义Android组件之带图像的TextView
- 新书内容连载(1):自定义Android组件之带图像的TextView
- Android Ringtone 自定义铃声介绍
- 新书内容连载(1):自定义Android组件之带图像的TextView
- Android中使用自定义Adapter(二)
- Study on Android【五】--自定义ContentProvider的语义
- 【转】Android自定义控件中自定义属性的处理方式
- Android高手进阶教程(三)之----Android 中自定义View的应用.
- android构建自定义的视图组件
- Android 自定义 LinearLayout
- Android (界面编程#8-自定义组件)
- Android基础教程(九)之自定义下拉菜单模式----Spinner与setDropDownViewResource的应用
- Android开发中自定义View设定到FrameLayout布局中实现多组件显示
- android开发之自定义组件
- android构建自定义的视图组件
- 自定义Android组件之带图像的TextView(转)