Android自定義view之彈出式dialog
閒談:
發覺好久沒有寫長部落格了,一是自己處於忙碌狀態,沒有時間寫,其實最主要的還是歸咎於自己太懶了。天下武功,唯懶不破。那就做一隻早起的鳥兒吧。
前言:
在初學android的時候,就一直覺得系統的dialog寫的簡直是醜爆了,看到很多app都用了自己自定義的,感覺效果超棒,心想,哪天自己也有這個水平就好了,於是乎,下定決心,好好學習android。廢話太多了,趕緊今天的教程吧。
正文:
今天我們要實現的效果圖是這樣的:
這樣的dialog比原生的好看多了,至少我是這樣認為的。其實做出這樣一個效果還是不難的,程式碼來說,也不是很多。
專案結構圖:
要學習這篇部落格,首先要會一些常見的自定義style,和常見的android基礎,我們這邊沒有用到自定義屬性。
先來看看我們的主要佈局吧。主要佈局也就只有三個button,我就不詳細說明怎麼佈局了,直接把程式碼貼上來了。
activity_main.xml:
當然這邊有些color,dimen,也貼出來。<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/color_gray_normal" android:gravity="center_horizontal" android:orientation="vertical" > <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/selector_btn_blue" android:padding="@dimen/dip10" android:text="btn1" /> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/dip10" android:background="@drawable/selector_btn_blue" android:padding="@dimen/dip10" android:text="btn2" /> <Button android:id="@+id/btn3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/dip10" android:background="@drawable/selector_btn_blue" android:padding="@dimen/dip10" android:text="btn3" /> </LinearLayout>
colors.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="color_blue_lighted">#539ad6</color> <color name="color_blue_normal">#61b1f4</color> <color name="color_gray_normal">#f5f5f5</color> <color name="color_gray_lighted">#efefef</color> <color name="color_white">#FFFFFF</color> <color name="color_border_white">#e5e5e5</color> <color name="color_gray">#999999</color> </resources>
dimens.xml
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="cornerRadius_size">3dip</dimen>
<dimen name="dip10">10dip</dimen>
<dimen name="dip12">12dip</dimen>
<dimen name="dip14">14dip</dimen>
<dimen name="dip16">16dip</dimen>
<dimen name="dip18">18dip</dimen>
<dimen name="dip20">20dip</dimen>
<dimen name="dip8">8dp</dimen>
<dimen name="sp16">16sp</dimen>
</resources>
selectors太多了,我就不把主要篇幅花在這個上面了,需要的自行下載我稍後貼出的下載地址,或者去我的github地址clone一下吧。
現在開始我們今天重中之重的內容了。
因為我們需要用自己定義的dialog,那麼我們就需要自定義個dialog的佈局檔案。分析一下上面的dialog效果,無非是一個想要顯示的texview的主要內容,還有一個分隔線,最後還有兩個button就完事了。
好,開始寫我們的佈局檔案,也就是layout_common_dialog.xml:
<?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:background="#00000000"
android:gravity="center" >
<LinearLayout
android:id="@+id/llSuccessBoard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/corner_btn_white_normal"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/dip20" >
<TextView
android:id="@+id/tvPromptMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dip18"
android:text="提示"
android:textColor="#444444"
android:textSize="@dimen/sp16" />
<TextView
android:layout_width="match_parent"
android:layout_height="1dip"
android:background="#eeeeee" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/dip14"
android:orientation="horizontal" >
<Button
android:id="@+id/btnCancle"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:background="@drawable/selector_btn_gray"
android:gravity="center"
android:paddingBottom="@dimen/dip8"
android:paddingLeft="@dimen/dip10"
android:paddingRight="@dimen/dip10"
android:paddingTop="@dimen/dip8"
android:text="取消"
android:textColor="@color/color_gray"
android:textSize="@dimen/sp16" />
<Button
android:id="@+id/btnSure"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:background="@drawable/selector_btn_blue"
android:gravity="center"
android:paddingBottom="@dimen/dip8"
android:paddingLeft="@dimen/dip10"
android:paddingRight="@dimen/dip10"
android:paddingTop="@dimen/dip8"
android:text="確定"
android:textColor="@color/color_white"
android:textSize="@dimen/sp16" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
當然,這個佈局檔案也沒什麼好說的,應該都是看得懂的,我們到時候就是通過這個佈局檔案inflater成一個view,設定原生dialog的contentView。
需要完成上述效果,還要定製一下我們的dialog風格,不然,你以為的灰色暗背景哪裡來的。那我們就在styles.xml檔案中定製一下風格吧。
styles.xml:
<resources>
<style name="commonDialog" parent="@android:style/Theme.Dialog">
<!-- Dialog的windowFrame框為無 -->
<item name="android:windowFrame">@null</item>
<!-- 沒有標題 -->
<item name="android:windowNoTitle">true</item>
<!-- 透明背景顏色 -->
<!-- <item name="android:windowIsTranslucent">false</item>:是否半透明 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 是否浮動內容在activity之上 -->
<item name="android:windowContentOverlay">@null</item>
<!-- 是否浮現在activity之上 -->
<item name="android:windowIsFloating">false</item>
<!-- 是否允許全屏 -->
<item name="android:windowFullscreen">false</item>
<!-- 是否允許背景灰暗 -->
<item name="android:backgroundDimEnabled">true</item>
</style>
</resources>
講到這裡,我們的所有佈局和準備工作就算是完成了,開始擼程式碼了。
CommonDialog.java:
package com.example.commondialog;
import android.app.Dialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
/**
* 通用彈出框
*
*/
public class CommonDialog {
private Dialog dialog;
Context context;
DialogPositiveListener positiveListener;
DialogNegativeListener negativeListener;
public CommonDialog(Context context) {
super();
this.context = context;
}
public void setPositiveListener(DialogPositiveListener positiveListener) {
this.positiveListener = positiveListener;
}
public void setNegativeListener(DialogNegativeListener negativeListener) {
this.negativeListener = negativeListener;
}
/**
* context promptMsg 提示資訊
* */
public Dialog initDialog(String promptMsg) {
return initDialog(promptMsg, "取消", "確認");
}
/**
* context promptMsg 提示資訊 cancleBtnMsg 取消按鈕資訊 sureBtnMsg 確認按鈕資訊
* */
public Dialog initDialog(String promptMsg, String cancleBtnMsg,String sureBtnMsg) {
View view = LayoutInflater.from(context).inflate(
R.layout.layout_common_dialog, null);
view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
dialog = ResultDialog.creatAlertDialog(context, view);
TextView tvPromptMsg = (TextView) view.findViewById(R.id.tvPromptMsg);
Button btnCancle = (Button) view.findViewById(R.id.btnCancle);
Button btnSure = (Button) view.findViewById(R.id.btnSure);
tvPromptMsg.setText(promptMsg);
btnCancle.setText(cancleBtnMsg);
btnSure.setText(sureBtnMsg);
btnCancle.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (negativeListener != null) {
negativeListener.onClick();
}
dialog.dismiss();
}
});
btnSure.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (positiveListener != null) {
positiveListener.onClick();
}
dialog.dismiss();
}
});
return dialog;
}
public interface DialogPositiveListener {
void onClick();
}
public interface DialogNegativeListener {
void onClick();
}
}
吶,上面的效果圖中可以看出,我們不僅可以只指定提示的內容,我們還可以指定button的內容是什麼。所以呢,我們需要構造兩個建立dialog的方法來初始化dialog。同時,我們也需要傳入兩個監聽器,來監聽兩個button的點選觸發事件。
我們在initDialog的時候建立我們的alertDialog,新開了一個類用來建立我們的dialog。
ResultDialog.java:
package com.example.commondialog;
import android.app.Dialog;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
/**
* view 檢視作為 dialog 彈出提示框
* */
public class ResultDialog {
static Dialog loading = null;
public static Dialog creatAlertDialog(Context context, View view) {
Dialog loading = new Dialog(context, R.style.commonDialog);
loading.setCancelable(true);
loading.setContentView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (LinearLayout.LayoutParams.MATCH_PARENT)));
return loading;
}
}
最主要的就是setContentVIew了,也就是我們之前提到過的哦,view也就是我們inflater的那個view。同時,我們也指定了dialog的風格,也是我們剛才定義的。其實寫到這裡我們的主要工作已經到了尾聲了。剩下的就是呼叫了。
MainActivity.java:
package com.example.commondialog;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.example.commondialog.CommonDialog.DialogNegativeListener;
import com.example.commondialog.CommonDialog.DialogPositiveListener;
public class MainActivity extends Activity implements OnClickListener {
private Button btn1;
private Button btn2;
private Button btn3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(this);
btn2 = (Button) findViewById(R.id.btn2);
btn2.setOnClickListener(this);
btn3 = (Button) findViewById(R.id.btn3);
btn3.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn1:
CommonDialog dialog1 = new CommonDialog(this);
dialog1.setPositiveListener(new DialogPositiveListener() {
@Override
public void onClick() {
ToastUtils.show(MainActivity.this, "確定");
}
});
dialog1.initDialog("您確定要刪除收藏?").show();
break;
case R.id.btn2:
CommonDialog dialog2 = new CommonDialog(this);
dialog2.setPositiveListener(new DialogPositiveListener() {
@Override
public void onClick() {
ToastUtils.show(MainActivity.this, "確定");
}
});
dialog2.setNegativeListener(new DialogNegativeListener() {
@Override
public void onClick() {
ToastUtils.show(MainActivity.this, "取消");
}
});
dialog2.initDialog("您確定要取消該收藏?").show();
break;
case R.id.btn3:
CommonDialog dialog3 = new CommonDialog(this);
dialog3.setPositiveListener(new DialogPositiveListener() {
@Override
public void onClick() {
ToastUtils.show(MainActivity.this, "再看看");
}
});
dialog3.setNegativeListener(new DialogNegativeListener() {
@Override
public void onClick() {
ToastUtils.show(MainActivity.this, "退出");
}
});
dialog3.initDialog("您確定現在退出app嗎?", "退出", "再看看").show();
break;
default:
break;
}
}
}
呼叫我就不詳細講了,對於一些基礎的toast工具的封裝啊,大家不會的就自行百度吧,我認為學習還是要靠自己的。
後語:
嗯,到這裡我們的專案就算是結束了。大家有沒有覺得不是很難(不敢說簡單)。
我創了一個QQ群:279031247,有興趣的可以加一下,一起學習,一起進步。