项目结构
基类BaseDialog
public abstract class BaseDialog extends Dialog{
public BaseDialog dialog;
public Activity activity;
public BaseDialog(@NonNull Activity activity) {
super(activity);
this.dialog=this;
this.activity=activity;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(initLayout());
DialogUtils.setWindowPublic(this);
initEvent();
}
public abstract int initLayout();
public abstract void initEvent();
/**
* 设置dialog其他屏幕地方是否触摸消失
* @param isSetCanceledOnTouchOutside
* @return
*/
public BaseDialog setCanceledOnTouchOutside(Boolean isSetCanceledOnTouchOutside) {
dialog.setCanceledOnTouchOutside(isSetCanceledOnTouchOutside);
return this;
}
/**
* 设置回退键是否有效
* @param isCancelable
* @return
*/
public BaseDialog setCancelable(Boolean isCancelable) {
dialog.setCancelable(isCancelable);
return this;
}
/**
* 显示dialog
* @return
*/
public BaseDialog showDialog() {
if(!isShowing()){
dialog.show();
}
return this;
}
/**
* 关闭dialog
* @return
*/
public BaseDialog hideDialog() {
if(isShowing()){
dialog.hide();
}
return this;
}
/**
* 设置回调 两个点击事件
*/
public CallBack callBack;
public interface CallBack{
void cancel();
void ok();
}
public BaseDialog setCallBack(CallBack callBack) {
this.callBack = callBack;
return this;
}
/**
* 设置点击一个条目
*/
public ClickSingleCallBack clickSingleCallBack;
public interface ClickSingleCallBack{
void click(String item);
}
public BaseDialog setClickSingleCallBack(ClickSingleCallBack clickSingleCallBack) {
this.clickSingleCallBack = clickSingleCallBack;
return this;
}
/**
* 设置照片回调
*/
public PhotoCallBack photoCallBack;
public interface PhotoCallBack{
void takePhoto();
void selectPhoto();
}
public BaseDialog setPhotoCallBack(PhotoCallBack photoCallBack) {
this.photoCallBack = photoCallBack;
return this;
}
}
解说
加载需要自定义dialog页面
setContentView(initLayout());
设置去除dialog状态栏黑色设置
DialogUtils.setWindowPublic(this);
设置点击事件处理
initEvent();
还有就是一些公用的设置,回退键是否有效、点击外面是否有效、关闭、显示dialog以及对于有“确认、取消”两个按键回调,对选择单个按钮按键回调。
DialogUtils工具类、提供动画效果设置等
public class DialogUtils {
public static void setWindowPublic(Dialog dialog){
Window window = dialog.getWindow();
int screenHeight = DensityUtils.getScreenHeight(dialog.getContext());
int statusBarHeight = DensityUtils.getStatusHeight(dialog.getContext());
int dialogHeight = screenHeight - statusBarHeight;
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, dialogHeight == 0 ? ViewGroup.LayoutParams.MATCH_PARENT : dialogHeight);
window.setBackgroundDrawableResource(R.color.colorTransparent);
}
/**
* 上到下
* @param dialog
*/
public static void setWindowAnimationsTop(Dialog dialog){
Window window = dialog.getWindow();
window.setWindowAnimations(R.style.dialog_animation);
}
/**
* 下到上
* @param dialog
*/
public static void setWindowAnimationsButtom(Dialog dialog){
Window window = dialog.getWindow();
window.setWindowAnimations(R.style.dialogWindowAnimButtomToTop);
}
}
在style.xml定义
<!--从低到顶动画效果-->
<style name="dialogWindowAnimButtomToTop" parent="android:Animation" mce_bogus="1">
<item name="android:windowEnterAnimation">@anim/dialog_enter_anim</item>
<item name="android:windowExitAnimation">@anim/dialog_exit_anim</item>
</style>
<style name="dialog_animation" parent="@android:style/Animation.Dialog">
<item name="android:windowEnterAnimation">@anim/push_bottom_in</item>
<item name="android:windowExitAnimation">@anim/push_bottom_out</item>
</style>
dialog_enter_anim
<?xml version="1.0" encoding="utf-8"?>
<!-- 弹出时动画 -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromYDelta="100%p"
android:toYDelta="0%p"
android:interpolator="@android:anim/accelerate_interpolator" />
</set>
dialog_exit_anim
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromYDelta="0%p"
android:toYDelta="100%p"
android:interpolator="@android:anim/accelerate_interpolator" />
</set>
push_bottom_in
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="1500"
android:fromYDelta="-100%p"
android:toYDelta="0" />
</set>
push_bottom_out
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="1500"
android:fromYDelta="0"
android:toYDelta="-100%p" />
</set>
如果不需要动画效果可以不调用这个工具类。
实现提示框
public class SelectDialog extends BaseDialog {
private TextView dialog_ok;
private TextView dialog_cancel;
private TextView dialog_content;
private String content;
public SelectDialog(@NonNull Activity activity,String content) {
super(activity);
this.content=content;
}
@Override
public void initEvent() {
dialog_content=findViewById(R.id.dialog_content);
dialog_ok=findViewById(R.id.dialog_ok);
dialog_cancel=findViewById(R.id.dialog_cancel);
getContent().setText(content);
findViewById(R.id.dialog_rl).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
hideDialog();
}
});
dialog_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(callBack!=null){
callBack.ok();
hideDialog();
}
}
});
dialog_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(callBack!=null){
callBack.cancel();
hideDialog();
}
}
});
}
@Override
public int initLayout() {
return R.layout.dialog_select;
}
public TextView getOk() {
return dialog_ok;
}
public TextView getCancel() {
return dialog_cancel;
}
public TextView getContent() {
return dialog_content;
}
}
解说
继承BaseDialog,一切变得更简单。加载自定义布局,对按钮监听回调;获取控件id以便于在调用可以改变一些属性,颜色,文本内容等。
布局文件
<?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="match_parent"
android:id="@+id/dialog_rl">
<LinearLayout
android:padding="10dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:background="@drawable/shape_dialog_common"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:padding="5dp"
android:layout_marginTop="3dp"
android:layout_width="match_parent"
android:gravity="left"
android:layout_height="wrap_content"
android:textColor="@color/colorBlackAA"
android:textSize="20sp"
android:text="提示"/>
<TextView
android:textColor="@color/colorBlackAA"
android:id="@+id/dialog_content"
android:textSize="16sp"
android:padding="10dp"
android:gravity="left"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="10"
android:minLines="1"
android:text="内容区"/>
<View
android:layout_width="match_parent"
android:layout_height="0.3dp"
android:background="@color/colorBlackAA"/>
<LinearLayout
android:layout_marginTop="3dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:textColor="@color/colorAccent"
android:id="@+id/dialog_cancel"
android:gravity="center"
android:textSize="16sp"
android:padding="10dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="取消"/>
<View
android:layout_marginTop="0.5dp"
android:layout_width="0.3dp"
android:layout_height="match_parent"
android:background="@color/colorBlackAA"/>
<TextView
android:textColor="@color/colorBlackAA"
android:id="@+id/dialog_ok"
android:textSize="16sp"
android:padding="10dp"
android:gravity="center"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="确认"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
调用及实现效果
new SelectDialog(this,"今天天气不错?").setCallBack(new BaseDialog.CallBack() {
@Override
public void cancel() {
show("不想搭理你。");
}
@Override
public void ok() {
show("very nice !");
}
}).showDialog();
实现带动画选择照片对话框
第一步、继承BaseDialog
public class SelectPhotoDialog extends BaseDialog {
private TextView dialog_selectpicture;
private TextView dialog_takepicture;
public SelectPhotoDialog(@NonNull Activity activity) {
super(activity);
}
@Override
public int initLayout() {
return R.layout.dialog_select_photo;
}
@Override
public void initEvent() {
DialogUtils.setWindowAnimationsButtom(this);
findViewById(R.id.dialog_rl).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
hide();
}
});
dialog_selectpicture = findViewById(R.id.dialog_selectpicture);
dialog_takepicture = findViewById(R.id.dialog_takepicture);
dialog_selectpicture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(photoCallBack!=null){
photoCallBack.selectPhoto();
hideDialog();
}
}
});
dialog_takepicture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(photoCallBack!=null){
photoCallBack.takePhoto();
hideDialog();
}
}
});
}
/**
* 获取选取照片控件
*
* @return
*/
public TextView getSelectpicture() {
return dialog_selectpicture;
}
/**
* 获取拍照照片控件
* @return
*/
public TextView getTakepicture() {
return dialog_takepicture;
}
}
对于布局文件
<?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="match_parent"
android:id="@+id/dialog_rl"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/colorWhite"
android:orientation="vertical">
<TextView
android:id="@+id/dialog_takepicture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text="拍照"
android:textSize="18sp" />
<View
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="@color/colorF7"/>
<TextView
android:id="@+id/dialog_selectpicture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text="选取"
android:textSize="18sp" />
<View
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="@color/colorF7"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text="取消"
android:textColor="@color/colorRed"
android:textSize="18sp" />
</LinearLayout>
</RelativeLayout>
解说
添加动画
DialogUtils.setWindowAnimationsButtom(this);
调用及运行效果
new SelectPhotoDialog(this).setPhotoCallBack(new BaseDialog.PhotoCallBack() {
@Override
public void takePhoto() {
show("takePhoto...");
}
@Override
public void selectPhoto() {
show("selectPhoto...");
}
}).showDialog();
进度条弹出框
public class NumberProgressDialog extends BaseDialog {
private NumberProgressBar numpb;
private TextView number_progress_tv;
private String tip;
public NumberProgressDialog(@NonNull Activity activity,String tip) {
super(activity);
this.tip=tip;
}
@Override
public void initEvent() {
numpb=findViewById(R.id.number_progress_bar);
numpb.setMax(100);
number_progress_tv=findViewById(R.id.number_progress_tv);
this.number_progress_tv.setText(tip);
}
@Override
public int initLayout() {
return R.layout.dialog_progress;
}
public NumberProgressBar getNumpb() {
return numpb;
}
public TextView getNumber_progress_tv() {
return number_progress_tv;
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp">
<LinearLayout
android:padding="20dp"
android:background="@color/colorWhite"
android:layout_centerInParent="true"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:padding="5dp"
android:layout_marginTop="3dp"
android:layout_width="match_parent"
android:gravity="left"
android:layout_height="wrap_content"
android:textColor="@color/colorBlackAA"
android:textSize="20sp"
android:text="提示"/>
<com.daimajia.numberprogressbar.NumberProgressBar
android:layout_marginTop="10dp"
android:id="@+id/number_progress_bar"
style="@style/NumberProgressBar_Default"
/>
<TextView
android:id="@+id/number_progress_tv"
android:padding="5dp"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:gravity="right"
android:layout_height="wrap_content"
android:text="下载进度"/>
</LinearLayout>
</RelativeLayout>
解说
NumberProgressBar 自定义控件使用代码家开源的,具体地址如下
compile 'com.daimajia.numberprogressbar:library:1.4@aar'
使用及运行效果
这个对话框是更新app时使用,具体调用dialog代码
private NumberProgressDialog pb;
pb=new NumberProgressDialog(mActivity,"下载进度");
pb.showDialog();
pb.getNumpb().setMax(100);
pb.getNumpb().incrementProgressBy(1);
pb.setCancelable(false);
在下载进度中更新当前进度
pb.getNumpb().setProgress(progress);
上面安装适配到Android9.0
实现加载Dialog
public class LodingDialog extends BaseDialog {
public LodingDialog(@NonNull Activity activity) {
super(activity);
}
@Override
public int initLayout() {
return R.layout.dialog_loding;
}
@Override
public void initEvent() {
setCancelable(false);
}
}
继承BaseDialog,设置回车无效,设置huit加载布局文件即可,就是这么简单!
<?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="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<LinearLayout
android:background="@drawable/shape_dialog_common"
android:padding="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.github.ybq.android.spinkit.SpinKitView
android:id="@+id/spin_kit"
style="@style/SpinKitView.Large.Circle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:SpinKit_Color="@color/colorBlack" />
</LinearLayout>
</LinearLayout>
解说
SpinKitView 使用库加载动画,设置样式可改变不同方式。
compile 'com.github.ybq:Android-SpinKit:1.1.0'
动画库效果
本Dialog使用及效果
设置开启dialog之后过30s自动关闭,实际情况可根据网络加载情况而定。
final LodingDialog lodingDialog=new LodingDialog(this);
lodingDialog.showDialog();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
lodingDialog.hideDialog();
}
},30000);
点击列表对话框
public class ClickSingleItemDialog extends BaseDialog {
private ListView click_single_lv;
private TextView tip;
private TextView title;
private List<String> mlist;
private String mTitle;
public ClickSingleItemDialog(@NonNull Activity activity,List<String> mlist) {
super(activity);
this.mlist=mlist;
}
public ClickSingleItemDialog(@NonNull Activity activity,List<String> mlist,String mTitle) {
super(activity);
this.mlist=mlist;
this.mTitle=mTitle;
}
@Override
public int initLayout() {
return R.layout.dialog_click_single;
}
@Override
public void initEvent() {
setCanceledOnTouchOutside(false);
title=findViewById(R.id.click_single_title);
click_single_lv=findViewById(R.id.click_single_lv);
tip=findViewById(R.id.click_single_tip);
findViewById(R.id.dialog_ll).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
hideDialog();
}
});
if(StringUtils.isNotNull(mTitle)){
title.setText(mTitle);
}
setListView();
}
/**
* 设置列表数据
*/
private void setListView() {
if(mlist==null){
click_single_lv.setVisibility(View.INVISIBLE);
tip.setVisibility(View.VISIBLE);
tip.setText(BasicKeys.KEY_NOT_NET);
return;
}
if(mlist.size()==0){
click_single_lv.setVisibility(View.INVISIBLE);
tip.setVisibility(View.VISIBLE);
tip.setText(BasicKeys.KEY_NULL);
return;
}else {
click_single_lv.setVisibility(View.VISIBLE);
tip.setVisibility(View.INVISIBLE);
}
click_single_lv.setAdapter(new CommonLvAdapter<String>(activity,mlist, R.layout.dialog_click_single_item) {
@Override
public void setData(BaseHolder holder, final String item, int position) {
holder.setText(R.id.click_single_item_tv,item);
holder.getView(R.id.click_single_item_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(clickSingleCallBack!=null){
clickSingleCallBack.click(item);
hideDialog();
}
}
});
}
});
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialog_ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="100dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:layout_marginTop="100dp"
android:background="@drawable/shape_dialog_common"
android:orientation="vertical">
<TextView
android:id="@+id/click_single_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:paddingTop="15dp"
android:paddingLeft="15dp"
android:text="提示"
android:textColor="@color/colorBlackAA"
android:textSize="20sp" />
<View
android:layout_marginTop="15dp"
android:layout_width="match_parent"
android:layout_height="0.7dp"
android:background="@color/colorBlackAA"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:id="@+id/click_single_lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@color/colorBlackAA"
android:dividerHeight="0.7dp"
android:scrollbars="none" />
<TextView
android:padding="15dp"
android:id="@+id/click_single_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:visibility="gone" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
单条item布局文件
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/click_single_item_tv"
android:text="123"
android:textSize="18sp"
android:textColor="@color/colorBlackAA"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:paddingLeft="15dp"
android:maxLines="1"
android:singleLine="true"/>
鸿洋大神listview适配器
public abstract class CommonLvAdapter<T> extends BaseAdapter {
protected Context mContext;
protected List<T> mListDatas;
protected LayoutInflater mInflater;
protected int mLayoutId;
public CommonLvAdapter(Context context, List<T> datas, int layoutId) {
this.mContext = context;
this.mListDatas = datas;
this.mInflater = LayoutInflater.from(context);
this.mLayoutId = layoutId;
}
@Override
public int getCount() {
return mListDatas == null ? 0 : mListDatas.size();
}
@Override
public T getItem(int position) {
return mListDatas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final BaseHolder viewHolder = getViewHolder(position, convertView, parent);
setData(viewHolder, getItem(position), position);
return viewHolder.getConvertView();
}
public abstract void setData(BaseHolder holder, T item, int position);
private BaseHolder getViewHolder(int position, View convertView, ViewGroup parent) {
return BaseHolder.get(mContext, convertView, parent, mLayoutId, position);
}
/**
* 缓存优化存储控件
*/
public static class BaseHolder {
private final SparseArray<View> mViews;
private View mConvertView;
protected int mPosition;
private BaseHolder(Context context, ViewGroup parent, int layoutId, int position) {
this.mViews = new SparseArray<View>();
this.mPosition = position;
mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
//setTag
mConvertView.setTag(this);
}
/**
* 拿到一个BaseHolderr对象
*
* @param context
* @param convertView
* @param parent
* @param layoutId
* @param position
* @return 来自鸿洋的博客
*/
public static BaseHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position) {
if (convertView == null) {
return new BaseHolder(context, parent, layoutId, position);
}
return (BaseHolder) convertView.getTag();
}
/**
* 通过控件的Id获取对于的控件,如果没有则加入views
*
* @param viewId
* @return
*/
public <T extends View> T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
public View getConvertView() {
return mConvertView;
}
public int getPosition() {
return mPosition;
}
/**
* 扩展方法
*/
public BaseHolder setText(int id, String text) {
if (text == null) {
text = "";
}
TextView tv = getView(id);
tv.setText(text);
return this;
}
public BaseHolder setImageResource(int id, int resId) {
ImageView iv = getView(id);
iv.setImageResource(resId);
return this;
}
public BaseHolder setVisible(int id) {
getView(id).setVisibility(View.VISIBLE);
return this;
}
public BaseHolder setInVisible(int id) {
getView(id).setVisibility(View.INVISIBLE);
return this;
}
public BaseHolder setGone(int id) {
getView(id).setVisibility(View.GONE);
return this;
}
}
}
使用及运行效果
List<String> list=new ArrayList();
int i=new Random().nextInt(4);
if(i==0){
list=null;
}
if(i==1){
list=new ArrayList();
for (int j = 0; j < 1 ; j++) {
list.add(String.valueOf(j));
}
}
if(i==2){
list=new ArrayList();
for (int j = 0; j < 5 ; j++) {
list.add(String.valueOf(j));
}
}
if(i==3){
list=new ArrayList();
for (int j = 0; j < 100 ; j++) {
list.add(String.valueOf(j));
}
}
new ClickSingleItemDialog(this,list).setClickSingleCallBack(new BaseDialog.ClickSingleCallBack() {
@Override
public void click(String item) {
show(item);
}
}).showDialog();
对于部分数据及无数据无网络友好兼容