【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

浙公网安备 33010602011771号