1. 程式人生 > >Android中建造者模式自定義Dialog

Android中建造者模式自定義Dialog

一、簡述

    由於Android系統的碎片化比較嚴重,加之Android採用開源方式,世界各大OEM廠商都對自家的Android系統進行了深度定製,那麼這些原因會給我們開發者帶來一些個麻煩,比如說,我們要開發一款App就要考慮到這款App儘量在不同系統和不同OEM深度定製的Android系統中彈出的對話方塊樣式介面相同,那麼這時候我們就不得不自定義自己的Dialog對話方塊。

二、實現的大體思路

 我在此會編寫一個demo,demo中設計一個類CommonDialog(當然這個類也是這個自定義Dialog的核心),這個類完成之後能夠像Android系統提供的AlertDialog一樣好用,那麼這個類的編寫的大致思路和所需的準備材料如下:

1、設計模式:   

 我們在自定義Dialog的時候採用的是建造者模式,如果對建造者模式不太熟悉的可以參考下這篇文章。我們在使用建造模式構建複雜物件時候通常會這樣做:

      ①由於是用Builder模式來建立某個物件,因此就沒有必要再定義一個Builder介面,直接提供一個具體的建造者類就可以了。

   對於建立一個複雜的物件,可能會有很多種不同的選擇和步驟,乾脆去掉“導演者”,把導演者的功能和Client的功能合併起來,也就是說,Client這個時候就相當於導演者,它來指導構建器類去構建需要的複雜物件。

2、樣式的定義:

    關於樣式的定義,一般情況下配置一些基本的屬性標籤,比如,背景顏色及透明程度、是否有標題  、是否浮現在activity之上等。

3、Dialog的佈局設計:

     我參照之前專案中的升級對話方塊就寫了一個類似的Dialog,如下圖:

                               

三、具體的程式碼實現

  1、那麼我們首先來自定義一個style樣式,該樣式繼承自Theme.Dialog,具體的程式碼實現如下:
      <style name="Dialog" parent="android:style/Theme.Dialog">
          <item name="android:background">@null</item>
          <item name="android:windowBackground">@android:color/transparent</item>
          <item name="android:windowNoTitle">true</item>
          <item name="android:windowIsFloating">true</item>
          <item name="android:spacing">350dp</item>
       </style>
          上面的樣式主要設定了一些對話方塊的基本資訊,這裡不再一一介紹。

2、按照上面給出的圖片所示,書寫的佈局檔案程式碼如下:

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

    <TextView
        android:id="@+id/tv_dialog_title"
        style="@style/dilog_header"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#e6e6fa"
        android:gravity="center_vertical"
        android:paddingLeft="20.0dp" />

    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#63B8FF" />

    <LinearLayout
        android:id="@+id/dialog_llyout_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center" >

        <TextView
            android:id="@+id/dialog_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/textview_border"
            android:lineSpacingMultiplier="1.5"
            android:minHeight="80.0dp"
            android:paddingBottom="15.0dp"
            android:paddingLeft="20.0dp"
            android:paddingRight="20.0dp"
            android:paddingTop="15.0dp"
            android:textSize="18sp" 
            android:textColor="#000000"
            />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#B4CDCD" />

    <LinearLayout
        android:id="@+id/dialog_btn"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/tv_dialog_pos"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#e6e6fa"
            android:gravity="center"
            android:text="下次再說"
            android:textColor="#000000" />

        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="#B4CDCD" />

        <TextView
            android:id="@+id/tv_dialog_neg"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#e6e6fa"
            android:gravity="center"
            android:text="立即升級"
            android:textColor="#000000" />
    </LinearLayout>

</LinearLayout>

3、利用建造者模式編寫核心類:

   、CommonDialog類

        這個CommonDialog作為建造物件其實並沒有什麼具體的邏輯問題,程式碼如下:

   public class CommonDialog extends Dialog {
                 public CommonDialog(Context context) {
                         super(context);
                 }

                 public CommonDialog(Context context, int themeResId) {
                          super(context, themeResId);
                 }

                  protected CommonDialog(Context context, boolean cancelable,
                          OnCancelListener cancelListener) {
                          super(context, cancelable, cancelListener);
                   }
 
             }

  ②Builder類

      這個類作為建造CommonDialog的核心類,它所建造的物件和實現的邏輯不是那麼簡單,而且它與CommonDialog的關係相當的曖昧,所以我們就將Builder作為CommonDialog的內部類,具體的程式碼如下:

/**
 * 自定義Dialog類---CommonDialog
 * 
 * @Time 2016年3月10日
 * @author lizy18
 */
public class CommonDialog extends Dialog {
 public CommonDialog(Context context) {
  super(context);
 }

 public CommonDialog(Context context, int themeResId) {
  super(context, themeResId);
 }

 protected CommonDialog(Context context, boolean cancelable,
   OnCancelListener cancelListener) {
  super(context, cancelable, cancelListener);
 }

 public static class Builder {
  private Context context;
  private String title;
  private String message;
  private String positiveButtonContent;
  private String negativeButtonContent;
  private OnClickListener positiveButtonListener;
  private OnClickListener negativeButtonListener;
  private View contentView;

  /**
   * 建造器的構造方法:
   * 
   * @param context
   */
  public Builder(Context context) {
   this.context = context;
  }

  /**
   * 利用字串設定title
   * 
   * @Time 2016年3月10日
   * @Author lizy18
   * @param title
   * @return Builder
   */
  public Builder setTitle(String title) {
   this.title = title;
   return this;
  }

  /**
   * 利用資源id設定title
   * 
   * @Time 2016年3月10日
   * @Author lizy18
   * @param title
   * @return Builder
   */
  public Builder setTitle(int title) {
   this.title = (String) context.getText(title);
   return this;
  }

  public Builder setMessage(String message) {
   this.message = message;
   return this;
  }

  public Builder setPositiveButton(String text, OnClickListener listener) {
   this.positiveButtonContent = text;
   this.positiveButtonListener = listener;
   return this;
  }

  public Builder setPositiveButton(int textId, OnClickListener listener) {
   this.positiveButtonContent = (String) context.getText(textId);
   this.positiveButtonListener = listener;
   return this;
  }

  public Builder setNegativeButton(String text, OnClickListener listener) {
   this.negativeButtonContent = text;
   this.negativeButtonListener = listener;
   return this;
  }

  public Builder setNegativeButton(int textId, OnClickListener listener) {
   this.negativeButtonContent = (String) context.getText(textId);
   this.negativeButtonListener = listener;
   return this;
  }

  public Builder setContentView(View v) {
   this.contentView = v;
   return this;
  }

  public CommonDialog create() {
   /**
    * 利用我們剛才自定義的樣式初始化Dialog
    */
   final CommonDialog dialog = new CommonDialog(context,
     R.style.Dialog);
   /**
    * 下面就初始化Dialog的佈局頁面
    */
   LayoutInflater inflater = (LayoutInflater) context
     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   View dialogLayoutView = inflater.inflate(R.layout.dialog_layout,
     null);
   dialog.addContentView(dialogLayoutView, new LayoutParams(
     LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
   if (!TextUtils.isEmpty(title)) {
    ((TextView) dialogLayoutView.findViewById(R.id.tv_dialog_title))
      .setText(title);
   } else {
    Log.w(context.getClass().toString(), "未設定對話方塊標題!");
   }
   if (!TextUtils.isEmpty(message)) {
    ((TextView) dialogLayoutView.findViewById(R.id.dialog_content))
      .setText(message);
   } else if (contentView != null) {
    ((LinearLayout) dialogLayoutView
      .findViewById(R.id.dialog_llyout_content))
      .removeAllViews();
    ((LinearLayout) dialogLayoutView
      .findViewById(R.id.dialog_llyout_content)).addView(
      contentView, new LayoutParams(
        LayoutParams.MATCH_PARENT,
        LayoutParams.WRAP_CONTENT));
   } else {
    Log.w(context.getClass().toString(), "未設定對話方塊提示內容!");
   }

   if (!TextUtils.isEmpty(positiveButtonContent)) {
    ((TextView) dialogLayoutView.findViewById(R.id.tv_dialog_pos))
      .setText(positiveButtonContent);
    if (positiveButtonListener != null) {
     ((TextView) dialog.findViewById(R.id.tv_dialog_pos))
       .setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
         positiveButtonListener.onClick(dialog, -1);
        }
       });

    }
   } else {
    ((TextView) dialogLayoutView.findViewById(R.id.tv_dialog_pos))
      .setVisibility(View.GONE);
   }

   if (!TextUtils.isEmpty(negativeButtonContent)) {
    ((TextView) dialogLayoutView.findViewById(R.id.tv_dialog_neg))
      .setText(negativeButtonContent);
    if (negativeButtonListener != null) {
     ((TextView) dialogLayoutView
       .findViewById(R.id.tv_dialog_neg))
       .setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
         negativeButtonListener.onClick(dialog, -2);
        }
       });
    }
   } else {
    ((TextView) dialogLayoutView.findViewById(R.id.tv_dialog_neg))
      .setVisibility(View.GONE);
   }
   /**
    * 將初始化完整的佈局新增到dialog中
    */
   dialog.setContentView(dialogLayoutView);
   /**
    * 禁止點選Dialog以外的區域時Dialog消失
    */
   dialog.setCanceledOnTouchOutside(false);
   return dialog;
  }
 }

}

4、測試      我們的所有工作到此結束,現在我們要看一下如何呼叫並測試一下好不好用,核心程式碼如下:
private void showCommonDialog() {
  CommonDialog.Builder builder = new CommonDialog.Builder(this);
  builder.setTitle("升級提示");
  builder.setMessage("發現新版本,請及時更新");
  builder.setPositiveButton("立即升級", new OnClickListener() {

   @Override
   public void onClick(DialogInterface dialog, int which) {
    dialog.dismiss();
    Toast.makeText(MainActivity.this, "開始下載吧", Toast.LENGTH_SHORT)
      .show();
   }
  });
  builder.setNegativeButton("下次再說", new OnClickListener() {

   @Override
   public void onClick(DialogInterface dialog, int which) {
    dialog.dismiss();
    Toast.makeText(MainActivity.this, "過幾日再下載也不遲呀",
      Toast.LENGTH_SHORT).show();
   }
  });

  builder.create().show();
 }

經過測試還不錯!另外我附上這個demo的完整程式碼並希望大家能夠一起交流共同進步!
 

相關推薦

Android建造模式定義Dialog

一、簡述     由於Android系統的碎片化比較嚴重,加之Android採用開源方式,世界各大OEM廠商都對自家的Android系統進行了深度定製,那麼這些原因會給我們開發者帶來一些個麻煩,比如說,我們要開發一款App就要考慮到這款App儘量在不同系統和不同OEM深度定

AndroidRxJava使用9----定義圖片快取框架

操作符:concat 不交錯的發射兩個或多個Observable的發射物 原理: 圖片快取框架,原理 1)檢查圖片是否在記憶體中快取 2)如果不在,檢查圖片是否在檔案中快取 3)如果不在,則從網路上拿圖片 下面程式碼只說明原理,真正實現功能,下載原始碼 1、在

Android使用ClassLoader修改定義異常類繼承來使異常捕獲失效來坑害你的同事

原理:使用熱修復的原理,用ClassLoader載入同名替換類。根據類的載入機制,一個類只會被載入一次,所以可以使用ClassLoader載入一個同名的、Throwable子類中的非異常類的類,來使異常捕獲失效 首先,定義一個自定義異常 public class Fool

Android的通知和定義通知佈局

Android中的通知(Notification)是Android中的重要一部分,應用程式通過通知來提醒使用者或者向用戶傳達資訊,下面讓我們來看一下怎麼在我們的程式中使用通知和自定義通知的佈局。 首先我們來看一下怎麼向通知欄中傳送一個通知。由於各個版本的And

android 回撥介面學習(定義Dialog 獲取資料資料回撥)

功能: 將單獨的一個Dialog提取出來以複用程式碼,然後在activity中去new 一個Dialog出來,能夠獲取Dialog選取的資料; 具體實現 TopicSingleChoiceDialog.java private int topicID=

Android之UI--打造萬能定義Dialog

在我們開發app的時候,很多地方需要彈出一個對話方塊,我們要不就直接用系統的Dialog或者就是AlertDialog,但是美工給我們的效果圖片很多都是無法去實現的。接下來我們來看下自定義Dialog的使用方法:首先我給大家展示2個圖片: 上面的

Android觀察模式(Observable)的理解

對於觀察者模式還是第一次接觸,今天在上網看了些資料瞭解了一下,大意瞭解了…… 定義:“定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變的時候,所有依賴於它的物件都將得到通知,並自動更新”,這就是所謂的觀察者模式,照意思理解那麼就一定會有觀察者和被觀察者了,在Jav

定義dialog建造模式

效果圖: Styles.xml <style name="updateStyleDialog" parent="android:Theme.Dialog"> <item name="android:windowFrame">@nul

Android定義Dialog樣式

public class MyMiddleDialog extends Dialog { private Context context; public MyMiddleDialog(Context context) { sup

Android的設計模式--建造模式

之前只知道建造者典型例子是AlertDialog,它的基本寫法是 public class AlertDialog extends Dialog implements DialogInterface { private AlertControlle

AndroidDialog的常用方法彙總和定義Dialog的步驟.txt

一、系統自帶Dialog對話方塊的使用: 警告框(AlertDialog)是在專案中出現的最簡單的一種對話方塊,主要的目的是為使用者顯示一條警告資訊,AlertDialog也是在對話方塊中使用最多的一個類,而且是Dialog的直接子類,此類繼承結構如下: j

Android 定義Dialog類,並在Activity實現按鈕監聽。

實際開發中,經常會用到Dialog,比如退出時候會彈出是否退出,或者還有一些編輯框也會用Dialog實現,效果圖如下: 開發中遇到的問題無非在於如果在Activity中監聽這個Dialog中實現的按鈕,Dialog類如下,在MyDialog這個類中實現了一個LeaveMyDialogLi

Android定義Dialog對話方塊消除邊距消除黑邊框和顯示動畫

這兩天練習一個專案 顯示對話方塊類似於QQ發表說說,寬是充滿螢幕的 並且有上下的顯示隱藏動畫 但是AlertDialog預設顯示模式是有邊距的 用了很多方法怎麼也消除不了AlertDialog的邊距 如下圖這樣 後來選擇使用Dialog消除了預設邊距的

建造模式—設計角度重溫DNF的角色

必須 face head sta 嘟嘟 裝備 body 控制 客戶    應用場景   假設現在我們要設計DNF中的人物角色(鬼劍士、神槍手、魔法師、聖騎士、格鬥家)。然而,利用面對對象的思想,必須先從實體入手,每一個角色都包含各種裝備、武器、配飾,這些就當做要建造的零

android 定義dialog的實現方法

listener params .get animator miss nim style wrap 參數 最近一直在做 java 相關的東西, 雖然一直在看 Android 但感覺有點留於理論,總這樣畢竟不行,寫的多不一定懂得多,但要想懂得多就一定要寫的多,於是今天動手寫了

Android定義Dialog多選對話框(Dialog+Listview+CheckBox)

dia bundle adapter get etl wrap 點擊 所有 技術 先放效果截圖 項目中需要有個Dialog全選對話框,點擊全選全部選中,取消全選全部取消。下午查了些資料,重寫了一下Dialog對話框。把代碼放出來。 public class MainAct

(轉精通Python設計模式)Python設計模式之創建型模式——2.建造模式

生成 需要 結構 progress per 展示 有意 odi con   建造者模式將一個復雜對象的構造過程與其表現分離,這樣,同一個構造過程可用於創建多個不同的表現。   我們來看個實際的例子,假設我們想要創建一個HMTL頁面生成器,HTML頁面的基本結構(構造組件)

Java的設計模式(八):建造模式

伸縮 null clas 示例代碼 最簡 裝配 角色扮演 app 但是 介紹 今天我們將研究java中的Builder模式。Builder 設計模式是一種創造性的設計模式,如工廠模式和抽象工廠模式。 當Object包含許多屬性時,引入了Builder模式來解決Factory

必須做作業三:某Android端點餐App觀察模式解析

onclick https 直接 tro lstat strong set lis drag 該項目還在開發中,目前開發了原型界面,是為了實現顧客從點餐到付款的全行為流程。並且提供菜品的詳情頁面和其他服務接口。 在此就以點餐界面的實現為例,分析該項目的觀察者模式 一、模

android設計模式——建造模式

Builder模式就是相比於一輛汽車有各個部件 但是不同的汽車有不同的部件 但是裝配成一輛車的方法相同 例子:比如肯德基有漢堡,雞翅,可樂,但是不同的套餐 是不同的組合 使用場景: 相同的方法,不同的執行順序產生不同的結果, 多個部件或零件,都可以裝配到一個物件中,但是產生的