Trang chủ > Android > Lập trình Android-Tạo Custom Dialog trong ứng dụng

Lập trình Android-Tạo Custom Dialog trong ứng dụng


Hiện nay một trong những đối thủ cạnh tranh mạnh mẽ nhất với iOS chính là Android, số lượng lập trình viên tham gia lập trình ứng dụng cho các thiết bị di động chạy trên hệ điều hành Android ngày càng trở nên đông đảo. Tài liệu hướng dẫn về lập trình Android được google cung cấp khá đầy đủ và chi tiết, các bạn có thể tham khảo trên website của google tại đây. Với ý định góp phần giúp các bạn mới bắt đầu lập trình Android giải quyết một số băn khoăn mà các bạn khó tránh khỏi khi bắt tay vào viết các ứng dụng ban đầu trong khi các bạn chưa thực sự quen thuộc hoặc chưa kịp tìm hiểu kĩ các API, blog này xin được cung cấp cho các bạn một số bài hướng dẫn, qua đó các bạn có thể nắm bắt, hiểu rõ hơn và tự xây dựng cho mình các kĩ năng trong lập trình Android. Bây giờ xin mời các bạn đến với bài đọc đầu tiên.
Trong bài đọc này, mình sẽ hướng dẫn các bạn tạo một Custom Dialog để thay thế cho Dialog sẵn có trong Android. Như chúng ta đã biết, Android có cung cấp một class là AlertDialog cùng với inner class của nó là Builder. Để tùy biến AlertDialog, chúng ta sẽ tùy biến AlertDialog và AlertDialog.Builder class, tạo custom theme, style và color để sử dụng cho mục đích tùy biến look and feel cho Custom Dialog của chúng ta. Sau khi hoàn thành chúng ta sẽ có một dialog như sau:

Viết các custom Layout, Color, Drawable, Style, String value và Theme

Trước hết chúng ta định nghĩa một số giá trị string để sử dụng trong ứng dụng này, mở file strings.xml và gán các giá trị cho nó:

<?xml version=“1.0” encoding=“utf-8”?>

<resources>

<string name=“app_name”>CustomDialog</string>

<string name=“default_dialog_btn”>Default Dialog</string>

<string name=“custom_dialog_btn”>Custom Dialog</string>

</resources>

Định nghĩa một số color mà ta sẽ sử dụng, trong thư mục values, tạo một file mới và đặt tên colors.xml sau đó định nghĩa các màu cơ bản mà ta sẽ dùng( ở đây mình định nghĩa 8 màu, tuy nhiên số lượng và tên các màu mà các bạn định nghĩa là hoàn toàn tùy thuộc ở các bạn):

<?xml version=“1.0” encoding=“utf-8”?>

<resources>

<color name=“red”>#ff0000</color>

<color name=“green”>#00ff00</color>

<color name=“blue”>#0000ff</color>

<color name=“black”>#000000</color>

<color name=“white”>#ffffff</color>

<color name=“grey”>#383838</color>

<color name=“yellow”>#ffff00</color>

<color name=“nocolor”>#11000000</color>

</resources>

Tiếp theo chúng ta sẽ tạo style cho titlemessage text của CustomDialog, những style này ta sẽ sử dụng cho việc định dạng text cho các component mà ta dùng trong layout. Các bạn hoàn toàn có thể bỏ qua file này và định dạng trực tiếp trong file layout, tuy nhiên mục đích của bài viết này là để các bạn làm quen với cách xây dựng và sử dụng các thành phần trong Android vì thế mình tách ra thành một file riêng. Tạo một file trong thư mục values và đặt tên là styles.xml, nội dung của file đó như sau:

<?xml version=“1.0” encoding=“utf-8”?>

<resources>

<style name=“DialogText”>

<item name=“android:textColor”>@color/white</item>

<item name=“android:textSize”>14sp</item>

</style>

<style name=“DialogText.Title”>

<item name=“android:textSize”>16sp</item>

<item name=“android:textStyle”>bold</item>

<item name=“android:textColor”>@color/yellow</item>

</style>

</resources>

Bây giờ ta sẽ tạo Theme cho CustomDialog, tạo mới một file có tên là themes.xml trong thư mục values với nội dung sau:

<?xml version=“1.0” encoding=“utf-8”?>

<resources>

<style name=“CustomDialog” parent=“android:style/Theme.Dialog”>

<item name=“android:windowBackground”>@color/nocolor</item>

<item name=“android:windowNoTitle”>true</item>

<item name=“android:windowIsFloating”>true</item>

</style>

</resources>

Các bạn chú ý rằng component mà chúng ta đang tạo là một Dialog vì thế ta sử dụng Dialog built-in theme của Android cho thuộc tính parent:

parent=“android:style/Theme.Dialog”

với thuộc tính này component của chúng ta khi hiển thị trên màn hình sẽ có dạng là một Dialog mà không phải là một Screen thông thường.

Các bạn có thể sử dụng các ảnh có có sẵn để style cho các components trong layout,  bên cạnh đó Android còn cung cấp cho chúng ta phương pháp để tạo ra các đối tượng Drawable của riêng mình, bây giờ mình sẽ tạo 3 đối tượng Drawable, mình sẽ sử dụng chúng cho phần header, content và footer của CustomDialog trong file layout. Trong thư mục drawable các bạn tạo 3 file .xml như sau:

dialog_custom_header.xml:

<?xml version=“1.0” encoding=“utf-8”?>

<shape xmlns:android=http://schemas.android.com/apk/res/android&#8221;

android:shape=“rectangle”>

<corners android:bottomRightRadius=“0dp”

android:bottomLeftRadius=“0dp”

android:topLeftRadius=“4dp”

android:topRightRadius=“4dp” />

<solid android:color=“#2A3B57” />

<stroke  android:width=“2dip”

android:top=“0dip”

android:color=“#94b66b”/>

</shape>

dialog_custom_content.xml:

<?xml version=“1.0” encoding=“utf-8”?>

<shape xmlns:android=http://schemas.android.com/apk/res/android&#8221;

android:shape=“rectangle”>

<solid android:color=“#567371” />

<stroke  android:width=“2dip”

android:bottom=“0dip”

android:color=“#94b66b”/>

<corners android:bottomRightRadius=“0dp”

android:bottomLeftRadius=“0dp”

android:topLeftRadius=“0dp”

android:topRightRadius=“0dp” />

</shape>

dialog_custom_footer.xml:

<?xml version=“1.0” encoding=“utf-8”?>

<shape xmlns:android=http://schemas.android.com/apk/res/android&#8221;

android:shape=“rectangle”>

<corners android:bottomRightRadius=“4dp”

android:bottomLeftRadius=“4dp”

android:topLeftRadius=“0dp”

android:topRightRadius=“0dp” />

<solid android:color=“#2A3B57” />

<stroke  android:width=“2dip”

android:color=“#94b66b”/>

</shape>

Kế tiếp chúng ta sẽ xây dựng layout cho CustomDialog. Trong thư mục layout, tạo một file và đặt tên là custom_dialog.xml với các thành phần sau:

<?xml version=“1.0” encoding=“utf-8”?>

<LinearLayout xmlns:android=http://schemas.android.com/apk/res/android&#8221;

android:orientation=“vertical”

android:layout_width=“fill_parent”

android:layout_height=“wrap_content”

android:minWidth=“280dip”>

<LinearLayout

android:orientation=“horizontal”

android:background=“@drawable/dialog_custom_header”

android:layout_width=“fill_parent”

android:layout_height=“wrap_content”>

<ImageView android:id=“@+id/custom_icon”

android:layout_margin=“5dip”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”/>

<TextView

android:id=“@+id/title”

android:padding=“8dip”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

style=“@style/DialogText.Title”/>

</LinearLayout>

<LinearLayout

android:id=“@+id/content”

android:orientation=“vertical”

android:background=“@drawable/dialog_custom_content”

android:layout_width=“fill_parent”

android:layout_height=“wrap_content”>

<TextView

android:id=“@+id/message”

android:padding=“5dip”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:maxWidth=“280dip”

style=“@style/DialogText”/>

</LinearLayout>

<LinearLayout

android:orientation=“horizontal”

android:background=“@drawable/dialog_custom_footer”

android:layout_width=“fill_parent”

android:layout_height=“wrap_content”>

<Button

android:id=“@+id/positive_btn”

android:layout_marginTop=“4dip”

android:layout_marginLeft=“4dip”

android:layout_marginRight=“2dip”

android:layout_width=“0dip”

android:layout_height=“wrap_content”

android:layout_weight=“1”

android:singleLine=“true”/>

<Button

android:id=“@+id/negative_btn”

android:layout_marginTop=“4dip”

android:layout_marginLeft=“2dip”

android:layout_marginRight=“4dip”

android:layout_width=“0dip”

android:layout_height=“wrap_content”

android:layout_weight=“1”

android:singleLine=“true”/>

</LinearLayout>

</LinearLayout>

Các bạn chú ý việc mình setMinWidth cho root layout, với minWidtht=280dip thì CustomDialog sẽ luôn chiếm khoảng 3/4 độ rộng màn hình của thiết bị. Khi message của CustomDialog quá dài, có thể sẽ làm cho độ rộng của nó ngang bằng với độ rộng màn hình thiết bị, vì vậy mình set maxWidth=280dip để độ rộng CustomDialog không thể vượt quá được 3/4 màn hình thiết bị.

Như vậy chúng ta đã hoàn thành phần tạo view cho CustomDialog, công việc tiếp theo mà chúng ta phải làm là tạo một lớp CustomDialog với một inner helper class có tên là Builder, dưới đây là code mà các bạn sẽ viết:

package net.danchanvit.example.android;

import android.app.Dialog;

import android.content.Context;

import android.content.DialogInterface;

import android.graphics.drawable.Drawable;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup.LayoutParams;

import android.widget.Button;

import android.widget.ImageView;

import android.widget.LinearLayout;

import android.widget.TextView;

/*

* Create custom Dialog window for your application, the custom Dialog

* rely on the custom layouts you define which allow you to create and

* use your custom look and feel

*/

public class CustomDialog extends Dialog {

public CustomDialog(Context context) {

super(context);

}

public CustomDialog(Context context, int theme) {

super(context, theme);

}

/*

* Helper class for creating custom Dialog

*/

public static class Builder {

private Context context;

private String iconUri;

private String title;

private String message;

private String positiveBtnText;

private String negativeBtnText;

private View contentView;

private DialogInterface.OnClickListener positiveBtnClickListener,

negativeBtnClickListener;

public Builder(Context context) {

this.context = context;

}

/**

* Set the Dialog icon from String

*

* @param icon

* @return

*/

public Builder setIconUri(String icon) {

this.iconUri = icon;

return this;

}

/**

* Set the Dialog icon from resource

*

* @param icon

* @return

*/

public Builder setIconUri(int icon) {

this.iconUri = (String) context.getText(icon);

return this;

}

/**

* Set the Dialog message from String

*

* @param message

* @return

*/

public Builder setMessage(String message) {

this.message = message;

return this;

}

/**

* Set the Dialog message from resource

*

* @param message

* @return

*/

public Builder setMessage(int message) {

this.message = (String) context.getText(message);

return this;

}

/**

* Set the Dialog title from resource

*

* @param title

* @return

*/

public Builder setTitle(int title) {

this.title = (String) context.getText(title);

return this;

}

/**

* Set the Dialog title from String

*

* @param title

* @return

*/

public Builder setTitle(String title) {

this.title = title;

return this;

}

/**

*Set a custom content view for the Dialog. If a  message is  set, the

* contentView is not added to the Dialog…

*

* @param v

* @return

*/

public Builder setContentView(View v) {

this.contentView = v;

return this;

}

/**

* Set the positive button resource and it’s listener

*

* @param positiveButtonText

* @param listener

* @return

*/

public Builder setPositiveButton(int positiveButtonText,

DialogInterface.OnClickListener listener) {

this.positiveBtnText = (String) context.getText(positiveButtonText);

this.positiveBtnClickListener = listener;

return this;

}

/**

* Set the positive button text and it’s listener

*

* @param positiveButtonText

* @param listener

* @return

*/

public Builder setPositiveButton(String positiveButtonText,

DialogInterface.OnClickListener listener) {

this.positiveBtnText = positiveButtonText;

this.positiveBtnClickListener = listener;

return this;

}

/**

* Set the positive button resource and it’s listener

*

* @param negativeButtonText

* @param listener

* @return

*/

public Builder setnegativeButton(int negativeButtonText,

DialogInterface.OnClickListener listener) {

this.negativeBtnText = (String) context.getText(negativeButtonText);

this.negativeBtnClickListener = listener;

return this;

}

/**

* Set the negative button text and it’s listener

*

* @param negativeButtonText

* @param listener

* @return

*/

public Builder setNegativeButton(String negativeButtonText,

DialogInterface.OnClickListener listener) {

this.negativeBtnText = negativeButtonText;

this.negativeBtnClickListener = listener;

return this;

}

/**

* Create the custom dialog

*/

public CustomDialog create() {

LayoutInflater inflater = (LayoutInflater) context

.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

// instantiate the dialog with the custom Theme

final CustomDialog dialog = new CustomDialog(context,

R.style.CustomDialog);

View layout = inflater.inflate(R.layout.custom_dialog, null);

dialog.addContentView(layout, new LayoutParams(

LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));

// set the dialog icon

if(iconUri != null && iconUri.length()>0){// Do not call this block of codes if we don’t use setIcon

int imgResource = context.getResources().getIdentifier(iconUri,

null, context.getPackageName());

Drawable drawable = context.getResources().getDrawable(imgResource);

((ImageView) layout.findViewById(R.id.custom_icon)).setBackgroundDrawable(drawable);

}

// set the dialog title

((TextView) layout.findViewById(R.id.title)).setText(title);

// set the confirm button

if (positiveBtnText != null) {

((Button) layout.findViewById(R.id.positive_btn))

.setText(positiveBtnText);

if (positiveBtnClickListener != null) {

((Button) layout.findViewById(R.id.positive_btn))

.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

positiveBtnClickListener.onClick(dialog,

DialogInterface.BUTTON_POSITIVE);

}

});

}

} else {

// if no confirm button just set the visibility to GONE

layout.findViewById(R.id.positive_btn).setVisibility(View.GONE);

}

// set the cancel button

if (negativeBtnText != null) {

((Button) layout.findViewById(R.id.negative_btn))

.setText(negativeBtnText);

if (negativeBtnClickListener != null) {

((Button) layout.findViewById(R.id.negative_btn))

.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

negativeBtnClickListener.onClick(dialog,

DialogInterface.BUTTON_NEGATIVE);

}

});

}

} else {

// if no confirm button just set the visibility to GONE

layout.findViewById(R.id.negative_btn).setVisibility(View.GONE);

}

// set the content message

if (message != null) {

((TextView) layout.findViewById(R.id.message)).setText(message);

} else if (contentView != null) {

// if no message set

// add the contentView to the dialog body

((LinearLayout) layout.findViewById(R.id.content))

.removeAllViews();

((LinearLayout) layout.findViewById(R.id.content)).addView(

contentView, new LayoutParams(

LayoutParams.WRAP_CONTENT,

LayoutParams.WRAP_CONTENT));

}

dialog.setContentView(layout);

return dialog;

}

}

}

Sử dụng CustomDialog trong Ứng dụng cụ thể

Trên đây là toàn bộ những gì các bạn phải làm để có được một custom dialog, Tuy nhiên để cho bài viết được rõ ràng hơn, tiếp theo mình sẽ trình bày cách gọi và hiển thị CustomDialog trong ứng dụng.

1. Tạo layout cho ứng dụng

Các bạn mở file layout main.xml và sửa lại như sau:

<?xml version=“1.0” encoding=“utf-8”?>

<LinearLayout xmlns:android=http://schemas.android.com/apk/res/android&#8221;

android:layout_width=“fill_parent”

android:layout_height=“fill_parent”>

<RelativeLayout android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_gravity=“center”

android:background=“@color/blue”>

<LinearLayout android:orientation=“vertical”

android:layout_width=“fill_parent”

android:layout_height=“wrap_content”

android:paddingTop=“3dip”>

<Button

android:id=“@+id/default_dialog_btn”

android:layout_width=“fill_parent”

android:layout_height=“wrap_content”

android:text=“@string/default_dialog_btn”/>

<Button

android:id=“@+id/custom_dialog_btn”

android:layout_width=“fill_parent”

android:layout_height=“wrap_content”

android:text=“@string/custom_dialog_btn”/>

</LinearLayout>

</RelativeLayout>

</LinearLayout>

2. Tạo Activity cho ứng dụng

Để cho nhanh chóng, ta sẽ đổi tên MainActivity thành CustomDialogActivity và sửa lại code như bên dưới:

package net.danchanvit.example.android;

import android.app.Activity;

import android.app.AlertDialog;

import android.app.Dialog;

import android.content.DialogInterface;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

public class CustomDialogActivity extends Activity implements View.OnClickListener{

public final int DEFAULT_DIALOG = 0;

public final int CUSTOM_DIALOG = 1;

Button default_dialog_btn, custom_dialog_btn;

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

default_dialog_btn = (Button) findViewById(R.id.default_dialog_btn);

custom_dialog_btn = (Button) findViewById(R.id.custom_dialog_btn);

default_dialog_btn.setOnClickListener(this);

custom_dialog_btn.setOnClickListener(this);

}

@Override

public void onClick(View view) {

if(view == default_dialog_btn){

CustomDialogActivity.this.showDialog(0);

}else if(view == custom_dialog_btn){

CustomDialogActivity.this.showDialog(1);

}

}

@Override

/*

* Build desired dialog

* CUSTOM or DEFAULT

*/

public Dialog onCreateDialog(int dialogId) {

Dialog dialog = null;

String icon = “drawable/dialog_icon”;

switch (dialogId) {

case CUSTOM_DIALOG :

CustomDialog.Builder customBuilder = new

CustomDialog.Builder(CustomDialogActivity.this);

customBuilder.setIconUri(icon).setTitle(“Custom Dialog Title”)

.setMessage(“Congratulation! You have successfully create a custom dialog. I hope    you enjoy it.”)

.setNegativeButton(“Cancel”,

new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which) {

CustomDialogActivity.this

.dismissDialog(CUSTOM_DIALOG);

}

})

.setPositiveButton(“Confirm”,

new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which) {

dialog.dismiss();

}

});

dialog = customBuilder.create();

break;

case DEFAULT_DIALOG :

AlertDialog.Builder alertBuilder = new

AlertDialog.Builder(CustomDialogActivity.this);

alertBuilder.setTitle(“Default title”)

.setMessage(“Default body”)

.setNegativeButton(“Cancel”,

new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which) {

dialog.dismiss();

}

})

.setPositiveButton(“Confirm”,

new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which) {

CustomDialogActivity.this

.dismissDialog(DEFAULT_DIALOG);

}

});

dialog = alertBuilder.create();

break;

}

return dialog;

}

}

Chạy ứng dụng và bạn sẽ thấy một màn hình như sau:

Bấm vào nút Default Dialog sẽ xuất hiện built-in AlertDialog của Android:

Và đây là CustomDialog mà chúng ta vừa tạo, xuất hiện khi các bạn bấm vào nút Custom Dialog từ màn hình chính:

Khá đơn giản, tuy nhiên cũng có không ít thao tác phải làm.Vậy là các bạn đã biết cách tạo một CustomDialog, từ đây bạn có thể chỉnh sửa và style lại theo ý muốn và sử dụng trong các ứng dụng của riêng mình. Các bạn có thể download toàn bộ source code của example trên tại đây để chạy thử. Nếu các bạn có thắc mắc gì cần được giúp đỡ trong lập trình Android, hãy gửi lại trong phần comment. Mình cũng rất mong các bạn khác đã là Pro trong lập trình Android cùng chia sẻ những hiểu biết và kinh nghiệm của chính các bạn để chúng ta cùng nhau bổ sung thêm các kỹ năng. Chúc các bạn lập trình vui vẻ!

Chuyên mục:Android
  1. Văn Linh
    02/11/2014 lúc 4:11 chiều

    cho em xin code này được không anh. Link trên die rồi. Em làm theo nhưng lỗi

  2. bravehoang
    21/07/2012 lúc 7:51 chiều

    Có thể thêm textbox vào Dialog được ko vậy bạn? Khi user click vào button, mình muốn hiện ra 1 dialog để nhập text vào, và khi close dialog thì trả giá trị nhập vào cho button xử lý thì làm thế nào nhỉ?

    • 21/07/2012 lúc 10:28 chiều

      Bạn có thể thêm một EditText vào Dialog tại thời điểm user click vào button trực tiếp bằng java code hoặc bạn có thể tạo một EditText ngay trong file .xml (nhớ set id cho nó) và thêm thuộc tính android:visibility=”invisible” để giấu nó đi. Khi user click vào button bạn dùng đoạn code sau để hiển thị EditText đó:

      EditText et = (EditText )findViewById(R.id.editTextId);
      et.setVisibility(View.VISIBLE);

      Để lấy giá trị user nhập vào bạn làm như sau:

      String text = et.getText().toString();

      Hy vọng thắc mắc của bạn được giải đáp.

      • HaiHack
        28/12/2012 lúc 9:21 sáng

        mình cũng đang thắc mắc chỗ này, cám ơn bạn ngheovodoi nhé

  1. No trackbacks yet.

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s

%d bloggers like this: