一个好看的Dialog样式实现,仿IOS

本文详细介绍了如何在Android开发中仿照iOS设计风格创建一个可复用的消息对话框,利用ListView和Dialog结合,通过XML布局和Java代码展示了从布局文件到Dialog实现的全过程,包括选中监听和取消按钮功能。

      消息对话框在实现Android原生态开发的过程中是十分重要的。该篇文章将讲述仿IOS的消息对话框的实现。具体代码来源于网路(忘记了具体文章来源)。
实现效果如下图:
在这里插入图片描述
      该消息对话框的实现主要使用到了listview和Dialog。当点击某个按钮时,弹出Dialog,Dialog上的view由listview实现。这样就实现了一个灵活的可复用的工具Dialog。具体代码如下。
首先给出XML布局文件和背景设置。
XML文件

<!-- dialog的布局view_dialog_select  dialog打开的实际上是这个view -->
<?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="match_parent"
    android:background="#00000000"
    android:gravity="bottom"
    android:orientation="vertical"
    android:padding="5dip" >
    
    <TextView
        android:id="@+id/mTv_Title"
        android:layout_width="match_parent"
        android:layout_height="68dp"
        android:layout_marginTop="5dip"
        android:background="@drawable/dialog_item_bg_only"
        android:padding="10dip"
        android:textColor="#0073FF"
        android:textSize="18sp"
        android:gravity="center"
        android:visibility="gone"/>

    <ListView
        android:id="@+id/dialog_list"
        android:layout_width="match_parent"
        android:dividerHeight="0.5dp"
        android:divider="#DAD9DB"
        android:layout_marginTop="5dip"
        android:listSelector="@android:color/transparent"
        android:cacheColorHint="@android:color/transparent"
        android:layout_height="wrap_content" >
    </ListView>

    <Button
        android:id="@+id/mBtn_Cancel"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="5dip"
        android:background="@drawable/dialog_item_bg_only"
        android:text="取消"
        android:gravity="center"
        android:textColor="#0073FF"
        android:textSize="18sp" />

</LinearLayout>

      listview所展示的每个item的布局文件view_dialog_item

<?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:orientation="vertical"
      >

    <TextView
        android:id="@+id/dialog_item_bt"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:gravity="center"
        android:textColor="#0073FF"
        android:textSize="18sp" />
</RelativeLayout>

布局文件用到的样式:

dialog_item_bg_buttom

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true"><shape>
            <solid android:color="#CACACB" />

            <corners android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" android:topLeftRadius="0dp" android:topRightRadius="0dp" />
        </shape></item>
    <item><shape>
            <solid android:color="#EBEBEB" />

            <corners android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" android:topLeftRadius="0dp" android:topRightRadius="0dp" />
        </shape></item>

</selector>

dialog_item_bg_center

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true"><shape>
            <solid android:color="#CACACB" />

        </shape></item>
    <item><shape>
            <solid android:color="#EBEBEB" />

        </shape></item>

</selector>

dialog_item_bg_only

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true"><shape>
            <solid android:color="#CACACB" />

            <corners android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" android:topLeftRadius="5dp" android:topRightRadius="5dp" />
        </shape></item>
    <item><shape>
            <solid android:color="#EBEBEB" />

            <corners android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" android:topLeftRadius="5dp" android:topRightRadius="5dp" />
        </shape></item>

</selector>

dialog_item_bg_top

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true"><shape>
            <solid android:color="#CACACB" />

            <corners android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" android:topLeftRadius="5dp" android:topRightRadius="5dp" />
        </shape></item>
    <item><shape>
            <solid android:color="#EBEBEB" />

            <corners android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" android:topLeftRadius="5dp" android:topRightRadius="5dp" />
        </shape></item>

</selector>

      上述为所有布局文件和背景设置,最主要的是view_dialog_select布局文件,在该文件中主要声明了一个listview控件。
Dialog的java代码

import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import java.util.List;
/**
 * dialog
 *
 */
public class SelectDialog extends Dialog implements OnClickListener,OnItemClickListener {
    private SelectDialogListener mListener;
    private Activity mActivity;
    private Button mMBtn_Cancel;
    private TextView mTv_Title;
    private List<String> mName;
    private String mTitle;
    private boolean mUseCustomColor = false;
    private int mFirstItemColor;
    private int mOtherItemColor;
    public interface SelectDialogListener {
        public void onItemClick(AdapterView<?> parent, View view, int position, long id);
    }
    private SelectDialogCancelListener mCancelListener;
    public interface SelectDialogCancelListener {
        public void onCancelClick(View v);
    }
    public SelectDialog(Activity activity, int theme,
                        SelectDialogListener listener,List<String> names) {
        super(activity, theme);
        mActivity = activity;
        mListener = listener;
        this.mName=names;
// 设置是否点击外围解散
        setCanceledOnTouchOutside(true);
    }
    /**
     * @param activity 调用弹出菜单的activity
     * @param theme 主题
     * @param listener 菜单项单击事件
     * @param cancelListener 取消事件
     * @param names 菜单项名称
     *
     */
    public SelectDialog(Activity activity, int theme,SelectDialogListener listener,SelectDialogCancelListener cancelListener ,List<String> names) {
        super(activity, theme);
        mActivity = activity;
        mListener = listener;
        mCancelListener = cancelListener;
        this.mName=names;
// 设置是否点击外围不解散
        setCanceledOnTouchOutside(false);
    }
    /**
     * @param activity 调用弹出菜单的activity
     * @param theme 主题
     * @param listener 菜单项单击事件
     * @param names 菜单项名称
     * @param title 菜单标题文字
     *
     */
    public SelectDialog(Activity activity, int theme,SelectDialogListener listener,List<String> names,String title) {
        super(activity, theme);
        mActivity = activity;
        mListener = listener;
        this.mName=names;
        mTitle = title;
// 设置是否点击外围可解散
        setCanceledOnTouchOutside(true);
    }
    public SelectDialog(Activity activity, int theme,SelectDialogListener listener,SelectDialogCancelListener cancelListener,List<String> names,String title) {
        super(activity, theme);
        mActivity = activity;
        mListener = listener;
        mCancelListener = cancelListener;
        this.mName=names;
        mTitle = title;
// 设置是否点击外围可解散
        setCanceledOnTouchOutside(true);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View view = getLayoutInflater().inflate(R.layout.view_dialog_select,
                null);
        setContentView(view, new LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.WRAP_CONTENT));
        Window window = getWindow();
// 设置显示动画
        window.setWindowAnimations(R.style.main_menu_animstyle);
        WindowManager.LayoutParams wl = window.getAttributes();
        wl.x = 0;
        wl.y = mActivity.getWindowManager().getDefaultDisplay().getHeight();
// 以下这两句是为了保证按钮可以水平满屏
        wl.width = LayoutParams.MATCH_PARENT;
        wl.height = LayoutParams.WRAP_CONTENT;
// 设置显示位置
        onWindowAttributesChanged(wl);
//setCanceledOnTouchOutside(false);
        initViews();
    }
    private void initViews() {
        DialogAdapter dialogAdapter=new DialogAdapter(mName);
        ListView dialogList=(ListView) findViewById(R.id.dialog_list);
        dialogList.setOnItemClickListener(this);
        dialogList.setAdapter(dialogAdapter);
        mMBtn_Cancel = (Button) findViewById(R.id.mBtn_Cancel);
        mTv_Title = (TextView) findViewById(R.id.mTv_Title);
//mMBtn_Cancel.setOnClickListener(this);
        mMBtn_Cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
// TODO Auto-generated method stub
                if(mCancelListener != null){
                    mCancelListener.onCancelClick(v);
                }
                dismiss();
            }
        });
        if(!TextUtils.isEmpty(mTitle) && mTv_Title != null){
            mTv_Title.setVisibility(View.VISIBLE);
            mTv_Title.setText(mTitle);
        }else{
            mTv_Title.setVisibility(View.GONE);
        }
    }
    @Override
    public void onClick(View v) {
        dismiss();
    }
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
                            long id) {
        mListener.onItemClick(parent, view, position, id);
        dismiss();
    }
    private class DialogAdapter extends BaseAdapter {
        private List<String> mStrings;
        private Viewholder viewholder;
        private LayoutInflater layoutInflater;
        public DialogAdapter(List<String> strings) {
            this.mStrings = strings;
            this.layoutInflater=mActivity.getLayoutInflater();
        }
        @Override
        public int getCount() {
// TODO Auto-generated method stub
            return mStrings.size();
        }
        @Override
        public Object getItem(int position) {
// TODO Auto-generated method stub
            return mStrings.get(position);
        }
        @Override
        public long getItemId(int position) {
// TODO Auto-generated method stub
            return position;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (null == convertView) {
                viewholder=new Viewholder();
                convertView=layoutInflater.inflate(R.layout.view_dialog_item, null);
                viewholder.dialogItemButton=(TextView) convertView.findViewById(R.id.dialog_item_bt);
                convertView.setTag(viewholder);
            }else{
                viewholder=(Viewholder) convertView.getTag();
            }
            viewholder.dialogItemButton.setText(mStrings.get(position));
            if (!mUseCustomColor) {
                mFirstItemColor = mActivity.getResources().getColor(R.color.dialog_blue);
                mOtherItemColor = mActivity.getResources().getColor(R.color.dialog_blue);
            }
            if (1 == mStrings.size()) {
                viewholder.dialogItemButton.setTextColor(mFirstItemColor);
                viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_only);
            } else if (position == 0) {
                viewholder.dialogItemButton.setTextColor(mFirstItemColor);
                viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_top);
            } else if (position == mStrings.size() - 1) {
                viewholder.dialogItemButton.setTextColor(mOtherItemColor);
                viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_buttom);
            } else {
                viewholder.dialogItemButton.setTextColor(mOtherItemColor);
                viewholder.dialogItemButton.setBackgroundResource(R.drawable.dialog_item_bg_center);
            }
            return convertView;
        }
    }
    public static class Viewholder {
        public TextView dialogItemButton;
    }
    /**
     * 设置列表项的文本颜色
     */
    public void setItemColor(int firstItemColor, int otherItemColor) {
        mFirstItemColor = firstItemColor;
        mOtherItemColor = otherItemColor;
        mUseCustomColor = true;
    }
}

      通过代码我们可以看到该类继承了Dialog类,并实现了两个点击事件的接口。可以通过查看Dialog类的代码得知,Dialog本质上和一个Activity存在的区别并不明显,当我们调用dialog.show方法时,Dialog开始调用太自身的onCreate方法。
      在这个SelectDialog类中我们提供了几个构造方法

public SelectDialog(Activity activity, int theme,SelectDialogListener listener,SelectDialogCancelListener cancelListener ,List<String> names);

      以这个构造方法为例,他需要提供一个显示该Dialog的activity,以及两种监听器的实现和一个String链表。
      其中activity表明Dialog在哪个主体界面上显示,而themo是表明显示的样式,SelectDialogListener 接口是指明listview的点击事件,SelectDialogCancelListener接口是点击取消按钮的点击事件,names是listview所要显示的内容。
      不得不说,Android开发在一定程度上写出的代码要比Java后台开发更惊艳,由于各种框架的出现,Java后台开发更偏重于业务,而对编码思想的运用并不常见(架构师负责的),Android的整体框架比较少见,因此Android开发更侧重基础。
SelectDialog的使用

    private void showDialog() {
        List<String> list = new ArrayList<>();
        list.add("拍照");
        list.add("相册");
        showDialog(new SelectDialog.SelectDialogListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                switch (position){
                    case 0:
                        break;
                    case 1:
                        break;
                    default:
                        break;
                }
            }
        },list);
    }
    private SelectDialog showDialog(SelectDialog.SelectDialogListener listener, List<String> list){
        SelectDialog dialog = new SelectDialog(this,
                R.style.transparentFrameWindowStyle,listener,list);
        dialog.show();
        return dialog;
    }
简介:基于DialogFragment的扩展,让dialog的使用更方便原理:http://www.jianshu.com/p/0529433d4522示例预览:基本用法:Step 1. 添加JitPack仓库 在当前项目等根目录下的 build.gradle 文件中添加如下内容:allprojects {     repositories {        ...         maven { url "https://jitpack.io" }     } }Step 2. 添加项目依赖dependencies {         compile 'com.github.Othershe:NiceDialog:1.1.0'}Step 3. 配置、展示dialogNiceDialog.init()           .setLayoutId(R.layout.dialog)     //设置dialog布局文件           .setConvertListener(new ViewConvertListener() {     //进行相关View操作的回调               @Override               public void convertView(ViewHolder holder, final BaseNiceDialog dialog) {               }           })           .setDimAmount(0.3f)     //调节灰色背景透明度[0-1],默认0.5f           .setShowBottom(true)     //是否在底部显示dialog,默认flase           .setMargin()     //dialog左右两边到屏幕边缘的距离(单位:dp),默认0dp           .setWidth()     //dialog宽度(单位:dp),默认为屏幕宽度           .setHeight()     //dialog高度(单位:dp),默认为WRAP_CONTENT           .setOutCancel(false)     //点击dialog外是否可取消,默认true           .setAnimStyle(R.style.EnterExitAnimation)     //设置dialog进入、退出的动画style           .show(getSupportFragmentManager());     //显示dialog注意: setMargin()和setWidth()选择一个即可更多用法:1、创建一个继承BaseNiceDialog的类,如果需要传参可仿照如下方式,也是就是常用的Fragment传参方式public class ConfirmDialog extends BaseNiceDialog {             private String type;             public static ConfirmDialog newInstance(String type) {                     Bundle bundle = new Bundle();         bundle.putString("type", type);                     ConfirmDialog dialog = new ConfirmDialog();         dialog.setArguments(bundle);                     return dialog;     }             @Override     public void onCreate(@Nullable Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                     Bundle bundle = getArguments();         type = bundle.getString("type");     }             @Override     public int intLayoutId() {                 return R.layout.dialog;     }             @Override     public void convertView(ViewHolder holder, final BaseNiceDialog dialog) {     } }2、展示dialogConfirmDialog.newInstance("1")              .setMargin(60)              .setOutCancel(false)              .show(getSupportFragmentManager());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值