zoukankan      html  css  js  c++  java
  • 【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

  • 相关阅读:
    virtual judge(专题一 简单搜索 C)
    virtual judge(专题一 简单搜索 B)
    virtual judge(专题一 简单搜索 A)
    HDU1548(楼梯问题bfs)
    Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2)D(思维,DP,字符串)
    Codeforces Round#522 Div2E(思维,背包,组合数学)
    Codeforces Round #522 Div2C(思维)
    Educational Codeforces Round 53C(二分,思维|构造)
    UPCOJ9526(SG函数打表,nim游戏异或规则)
    Wannafly挑战赛27B(DFS,链表头插法)
  • 原文地址:https://www.cnblogs.com/nerve/p/3185435.html
Copyright © 2011-2022 走看看