【android开发记录片】2.自定义/定制 Dialog组件

写在前面

好久没有更新android方面的博客,因为一直没搞,最近做一个小项目,用到了Dialog作弹出菜单 和 确认/输入框。这里跟大家分享一下我定制Dialog的方法。
下面是截图:

1.弹出菜单

   

2.确认框

 

3.输入框

 

4.颜色选择框

 

文件结构

包含dialog的封装类,layout文件,drawable文件。

 

 

 

 

 

实现

1.弹出菜单

首先定义对话框的事件接口:

	public interface MenuListener{
		/**
		 * @方法名称 :onClick
		 * @功能描述 :
		 * @param position 菜单项的下标
		 * @return :void
		 */
		public void onMenuClick(int code, int position);
	}
	
	public interface ConfirmListener{
		
		/**
		 * @方法名称 :onConfirmClick
		 * @功能描述 :当confirm对话框中的按钮被点击时
		 * @param position
		 * @return :void
		 */
		public void onConfirmClick(int position, Object obj);
	}


然后定义一个layout,里面放一个GridView就好,还定义GridView 的Item的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/RelativeLayout_Item"
	android:layout_width="fill_parent" android:layout_height="wrap_content"
	android:paddingBottom="1dip">
	
	<ImageView android:id="@+id/item_image"
		android:layout_centerHorizontal="true" 
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:contentDescription="@string/nothing" />
	
	<TextView android:layout_below="@id/item_image" android:id="@+id/item_text"
		android:layout_centerHorizontal="true" android:layout_width="wrap_content"
		android:layout_height="wrap_content" android:text="@string/nothing" />
</RelativeLayout>


接着是MenuDialog.java,内部有一个Dialog实例,对外提供show()方法:

public MenuDialog(Context context, int id) {
		this.context = context;
		this.id = id;
	}
	
	/**
	 * @方法名称 :creatDialog
	 * @功能描述 :创建一个菜单Dialog,需要有数据才得,否则 menuDialog 为null
	 * @param menuDialog
	 * @param data
	 * @return :void
	 */
	public void creatDialog(final MenuData data){
		if(data == null)
			return ;
		if(data.icons.length > 0){
			View view = View.inflate(context, getMenuLayout(), null);
			
			//优先使用图片作为背景
			if(data.bgResource != -1){
				view.setBackgroundDrawable(
						UIFactory.getRepeatBG(context,data.bgResource)
						);
			}else if(data.bgColor != -1){
				Log.i("CellNote", "set bgColor---------");
				view.setBackgroundColor(data.bgColor);
			}
			
			GridView gView = (GridView)view.findViewById(GRID_ID);
			gView.setAdapter(getMenuAdapter(data));
			
			dialog = new Dialog(context);
			dialog.show();
			Window win = dialog.getWindow();
			//将dialog的背景透明化
			win.setBackgroundDrawable(new ColorDrawable(0));
			win.setGravity(getGravity());
			win.setContentView(view);
			
			if(data.listener != null){
				//注册菜单事件
				gView.setOnItemClickListener(new OnItemClickListener() {

					@Override
					public void onItemClick(AdapterView<?> arg0, View arg1,
							int arg2, long arg3) {
						data.listener.onMenuClick(id,arg2);
						if(data.onlyOneTime)
							dialog.dismiss();
					}
				});
			}
			
			registerKey();
			
			this.hasMenu = true;
		}
	}
	
	/**
	 * @方法名称 :show
	 * @功能描述 :显示对话框
	 * @return :void
	 */
	public void show(){
		dialog.show();
	}


在Activity中如此调用:

@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add("danting");
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onMenuOpened(int featureId, Menu menu) {
		hideKeyboard();
		
		if (menuDialog == null) {
			menuDialog = new MenuDialog(this, MENU_OPTION);
			menuDialog.creatDialog(getMenuData());
			Log.i("CellNote","menuDialog create!!");
		}

		if(menuDialog.hasMenu)
			menuDialog.show();
		
		// 返回false 阻止系统的菜单
		return false;
	}


上面是一个父类Activity通用的产生弹出菜单的方法(在onCreateOptionsMenu()方法,menu.add("");是一定要的,不要的话不会弹出对话框,这个不解=.=),子类只需要重写 getMenuData()方法就可以产生菜单,如:

/**
	 * 产生菜单
	 */
	@Override
	public MenuData getMenuData() {
		MenuData data = new MenuData();
		data.icons = new int[]{
				R.drawable.ic_menu_color_home,
				R.drawable.ic_menu_color_category,
				R.drawable.ic_menu_color_note,
				R.drawable.ic_menu_color_search,
				R.drawable.ic_menu_color_setting,
				R.drawable.ic_menu_color_bag,
				R.drawable.ic_menu_color_help,
				R.drawable.ic_menu_color_about
			};
		data.labels = new String[]{"首页","新分类","新便签","内容搜索","设置","备份/还原","帮助","关于我们"};
		data.listener = this;
		data.bgResource = R.drawable.bg_green_32x32;
		
		return data;
	}


上面用到了一个MenuData类,如下:

/**
 * @项目名称 :CellNote
 * @文件名称 :MenuDialog.java
 * @所在包 :org.nerve.cellnote.view
 * @功能描述 :
 *	菜单数据体,其中 icons 是菜单的图像引用,labels 是菜单文字
 * @创建者 :集成显卡	1053214511@qq.com
 * @创建日期 :2013-1-23
 * @修改记录 :
 */
public static class MenuData{

	/**背景的drawable,如果为-1,则使用默认的背景*/
	public int bgResource = -1;
	/**背景颜色*/
	public int bgColor = -1;
	
	/**菜单点击监听器*/
	public MenuListener listener;
	/**为true时,菜单被点击后后自动消失*/
	public boolean onlyOneTime;
	
	public int[] icons = new int[0];
	public String[] labels;
	
	public MenuData(){
		this.onlyOneTime = true;
	}
	
	public MenuData(int [] is,String[] ls){
		this();
		this.icons = is;
		this.labels = ls;
	}
}

 

 

2.确认对话框

定义layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/shape_dialog"
    >
  
    <TextView 
        android:id="@+id/dialog_title"
        android:layout_width="fill_parent"
        android:layout_height="35dp"
        android:textSize="18sp"
        android:textColor="#000000"
        android:gravity="center"
        />
    
    <TextView 
        android:id="@+id/dialog_message"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:paddingBottom="2dp"
        android:textColor="#000000"
        />
    
    <!-- 这个可以自由添加视图 -->
    <LinearLayout 
        android:id="@+id/dialog_live"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
       >
       
    </LinearLayout>
    
    <LinearLayout 
        android:id="@+id/dialog_button_group"
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:paddingBottom="15dp">
        
        <Button 
            android:id="@+id/dialog_ok"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/dialog_ok"
            android:padding="3dp"
            android:background="@drawable/shape_dialog_button_ok"
            android:textColor="@color/black"
            android:layout_marginRight="10dp"/>
        
         <Button 
            android:id="@+id/dialog_cannel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/dialog_cannel"
            android:layout_marginLeft="10dp"
            android:textColor="@color/black"
            android:background="@drawable/shape_dialog_button_cannel"/>
        
    </LinearLayout>
</LinearLayout> 


然后是ConfirmDialog.java:

package org.nerve.cellnote.view.dialog;

import org.nerve.cellnote.R;
import org.nerve.cellnote.view.dialog.DialogHelper.ConfirmListener;

import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * @项目名称 :CellNote
 * @文件名称 :ConfirmDialog.java
 * @所在包 :org.nerve.cellnote.view.dialog
 * @功能描述 :
 *	确定对话框,显示标题,内容,还有确定和取消按钮
 * @创建者 :集成显卡	1053214511@qq.com
 * @创建日期 :2013-1-28
 * @修改记录 :
 */
public class ConfirmDialog {
	/**默认的对话框视图*/
	public static int DIALOG_UI = R.layout.dialog_main;
	
	/**默认的对话框占主屏幕多宽度的比例*/
	public static float WIDTH_SCALE = 0.8F;
	
	/**OK按钮被点击*/
	public static final int OK = 0;
	/**取消按钮点击*/
	public static final int CANNEL = 1;
	
	protected Context context;
	protected Dialog dialog;
	protected Button okBtn;
	protected Button cannelBtn;
	
	protected int id;
	protected String title;
	protected String message;
	
	protected ConfirmListener listener;
	
	public ConfirmDialog(Context context){
		this.context = context;
	}
	public ConfirmDialog(Context context, String t, String m){
		this(context);
		this.title = t;
		this.message = m;
	}
	
	public void setTitle(String t){
		this.title = t;
	}
	public void setMessage(String m){
		this.message = m;
	}
	public void setConfirmListener(ConfirmListener listener){
		this.listener = listener;
	}
	
	protected void createDialog(){
		View view = View.inflate(context, getMainXML(), null);
		
		((TextView)view.findViewById(R.id.dialog_title)).setText(title);
		
		//如果message为null,不显示
		TextView messageTV = (TextView)view.findViewById(R.id.dialog_message);
		if(message == null)
			((LinearLayout)view).removeView(messageTV);
		else
			messageTV.setText(message);
		
		dialog = new Dialog(context);
		dialog.show();
		Window win = dialog.getWindow();
		//将dialog的背景透明化
		win.setBackgroundDrawable(new ColorDrawable(0));
		win.setGravity(getGravity());
		
		LinearLayout ll = (LinearLayout)view.findViewById(R.id.dialog_live);
		View liveView = getLiveView();
		if(liveView != null){
			ll.addView(liveView);
		}
		
		win.setLayout(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
		win.setContentView(view);
		
		initButton(view);
	}
	
	public void show(){
		if(dialog == null)
			createDialog();
		else
			dialog.show();
	}
	
	/**
	 * @方法名称 :initButton
	 * @功能描述 :初始化按钮
	 * 	
	 * @param view
	 * @return :void
	 */
	protected void initButton(View view){
		if(isButtonShow()){
			okBtn = (Button)view.findViewById(R.id.dialog_ok);
			cannelBtn = (Button)view.findViewById(R.id.dialog_cannel);
			okBtn.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					dialog.dismiss();
					afterClickOK();
				}
			});
			
			cannelBtn.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					dialog.dismiss();
				}
			});
		}else{
			View v = view.findViewById(R.id.dialog_button_group);
			((LinearLayout)view).removeView(v);
		}
	}
	
	/**
	 * @方法名称 :isButtonShow
	 * @功能描述 :如果子类不需要显示按钮,可以重写这个方法。
	 * @return
	 * @return :boolean
	 */
	protected boolean isButtonShow(){
		return true;
	}
	
	/**
	 * @方法名称 :getMainXML
	 * @功能描述 :获得主视图id
	 * @return
	 * @return :int
	 */
	public int getMainXML(){
		return DIALOG_UI;
	}
	
	public int getGravity(){
		return Gravity.CENTER;
	}
	
	/**
	 * @方法名称 :afterClickOK
	 * @功能描述 :确认按钮点击后触发,子类可以重写这个方法达到不同的效果
	 * @return :void
	 */
	public void afterClickOK(){
		if(listener != null)
			listener.onConfirmClick(OK, null);
	}
	/**
	 * @方法名称 :getLiveView
	 * @功能描述 :得到一个扩展的视图,可以产生不同组合的对话框,子类可以重写这个方法
	 * @return
	 * @return :View
	 */
	public View getLiveView(){
		return null;
	}
}


子类可以通过重写一些方法再定义对话框。

调用方法:

ConfirmDialog cd = new ConfirmDialog(this);
cd.setTitle("关于我们");
		
StringBuilder about = new StringBuilder();
about.append("名称:"+getString(R.string.app_name));
about.append("\n版本:" + getString(R.string.app_version));
about.append("\n作者:" + getString(R.string.app_author));
about.append("\n简介:" + getString(R.string.app_information));
about.append("\n邮箱:" + getString(R.string.app_email));
		
cd.setMessage(about.toString());
cd.show();


 

3.输入对话框

dialog_single_input.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
      	android:paddingLeft="20dp"
	    android:paddingRight="20dp"
       >
      
    <EditText 
	    android:id="@+id/dialog_single_input"
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    android:hint="@null" />

</LinearLayout>


然后 SingleInputDialog 继承自 ConfirmDialog,重写getView() 方法,返回 上面的布局:

package org.nerve.cellnote.view.dialog;

import org.nerve.cellnote.R;

import android.content.Context;
import android.view.View;
import android.widget.EditText;

/**
 * @项目名称 :CellNote
 * @文件名称 :SingleInputDialog.java
 * @所在包 :org.nerve.cellnote.view.dialog
 * @功能描述 :
 *	只有一个输入的对话框,在这里,message 被设置为了:请输入
 * @创建者 :集成显卡	1053214511@qq.com
 * @创建日期 :2013-1-28
 * @修改记录 :
 */
public class SingleInputDialog extends ConfirmDialog{

	protected EditText singleInput;
	
	protected String defaultText;
	
	public SingleInputDialog(Context context) {
		super(context);
	}
	
	@Override
	public View getLiveView() {
		View lv = View.inflate(context, R.layout.dialog_single_input, null);
		this.singleInput = (EditText)lv.findViewById(R.id.dialog_single_input);
		this.singleInput.setText(defaultText);
		return lv;
	}
	
	@Override
	public void afterClickOK() {
		listener.onConfirmClick(OK, singleInput.getText().toString());
	}
	
	public void setDefaultText(String t){
		this.defaultText = t;
	}
}


调用方法:

SingleInputDialog sd = new SingleInputDialog(this);
		
		String title = getString(R.string.category_input);
		sd.setTitle(title);
		sd.setMessage(title + ":");
		
		sd.setConfirmListener(new ConfirmListener() {
			@Override
			public void onConfirmClick(int position, Object obj) {
				String name = (String)obj;
				newCategoryDo(name);
			}
		});
		sd.show();



恩,帖了好多代码,这里就源文件打包给大家下载,下载导入到自己的工程里便可以看到效果:http://download.csdn.net/detail/ssrc0604hx/5062435

posted @ 2013-02-12 22:26  集成显卡  阅读(252)  评论(0编辑  收藏  举报