[Android] Tạo custom Dialog với hiệu ứng Circular Reveal

1
Dịch vụ dạy kèm gia sư lập trình

Đã lâu rồi mình mới có thời gian rảnh để ngồi viết bài. Nhân tiện bị cách ly, mình muốn chia sẻ cách tạo dialog “đẹp xinh” với animation Circular Reveal uyển chuyển.

Các bạn xem ảnh demo bên dưới để biết kết quả sau khi thực hiện nhé!

[Android] Hướng dẫn tạo Dialog với hiệu ứng Circular Reveal

Các bước để tạo dialog trong Android

Note:  Các bạn chú ý nhé, Animation này yêu cầu SDK version tối thiểu là 21.

Bước 1: Tạo các file layout xml cho dialog và MainActivity

dialog.xml

<?xml version=”1.0" encoding=”utf-8"?>
<RelativeLayout
     xmlns:android=”http://schemas.android.com/apk/res/android"
     android:orientation=”vertical”
     android:layout_width=”match_parent”
     android:id=”@+id/dialog”
     android:layout_height=”match_parent”
     android:background=”@color/colorAccent”>
    <ImageView
        android:id=”@+id/closeDialogImg”
        android:layout_width=”30dp”
        android:layout_height=”30dp”
        android:layout_margin=”10dp”
        android:src=”@drawable/ic_close_black_24dp”
        android:tint=”#fff”/>
    <RelativeLayout
        android:layout_width=”match_parent”
        android:layout_height=”150dp”
        android:background=”#FFF”
        android:layout_centerInParent=”true”
        android:layout_marginEnd=”20dp”
        android:layout_marginStart=”20dp”
        android:orientation=”vertical”>
   <TextView
        android:layout_width=”wrap_content”
        android:layout_height=”wrap_content”
        android:layout_centerInParent=”true”
        android:text=”This is my Dialog”
        android:textSize=”24dp”/>
   </RelativeLayout>
</RelativeLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/activity_main"
    tools:context="beaststudio.in.revealanimation.MainActivity">


    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_margin="24dp"
        android:src="@drawable/ic_add_black_24dp"
        android:tint="#fff"
        />

</RelativeLayout>

Bước 2: viết logic hiển thị dialog trong java file

Sau khi đã có layout ngon lành cành đào, mình thực hiện viết code logic trong file Java. Phần logic này sẽ xử lý việc hiển thị dialog khi click vào floating button.

//MainActivity.java 
...
FloatingActionButton fab;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fab = (FloatingActionButton)findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                showDiag();
            }
        });
}

Như các bạn thấy đoạn code trên, chúng ta bắt sự kiện click của người dùng bằng API setOnClickListener. Trong đoạn xử lý sự kiện này mình có đặt sẵn hàm showDiag() để hiển thị dialog – nội dung hàm sẽ được đề cập bên dưới đây.

💦 Đọc thêm về xử lý sự kiện: Xử lý sự kiện trong Android (Event Handling)

Trong hàm hiển thị dialog, mình lưu ý đến một API quan trọng – revealShow(dialogView, true, dialog). Hàm này được dùng để tạo animation hình tròn khi hiển thị dialog.

Hàm này có 3 tham số cần truyền vào:

  • dialogView: Chính là view mà bạn nhồi vào layout xml đã tạo ở bước 1.
  • boolean: Nếu bạn muốn hiển thị dialog thì truyền giá trị TRUE. Muốn ẩn dialog thì truyền FALSE.
  • dialog: Tham số này bạn chỉ cần truyền dialog object vào là được.

Code hoàn chỉnh của hàm showDiag() như sau:

//MainActivity.java
...
private void showDiag() {

    final View dialogView = View.inflate(this,R.layout.dialog,null);

    final Dialog dialog = new Dialog(this,R.style.MyAlertDialogStyle);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setContentView(dialogView);

    ImageView imageView = (ImageView)dialog.findViewById(R.id.closeDialogImg);
    imageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            revealShow(dialogView, false, dialog);
        }
    });

    dialog.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialogInterface) {
            revealShow(dialogView, true, null);
        }
    });

    dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
        @Override
        public boolean onKey(DialogInterface dialogInterface, int i, KeyEvent keyEvent) {
            if (i == KeyEvent.KEYCODE_BACK){

                revealShow(dialogView, false, dialog);
                return true;
            }

            return false;
        }
    });



    dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));

    dialog.show();
}

Và đây là đoạn mã của hàm revelShow().

private void revealShow(View dialogView, boolean b, final Dialog dialog) {

    final View view = dialogView.findViewById(R.id.dialog);

    int w = view.getWidth();
    int h = view.getHeight();

    int endRadius = (int) Math.hypot(w, h);

    int cx = (int) (fab.getX() + (fab.getWidth()/2));
    int cy = (int) (fab.getY())+ fab.getHeight() + 56;


    if(b){
        Animator revealAnimator = ViewAnimationUtils.createCircularReveal(view, cx,cy, 0, endRadius);

        view.setVisibility(View.VISIBLE);
        revealAnimator.setDuration(700);
        revealAnimator.start();

    } else {

        Animator anim =
                ViewAnimationUtils.createCircularReveal(view, cx, cy, endRadius, 0);

        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                dialog.dismiss();
                view.setVisibility(View.INVISIBLE);

            }
        });
        anim.setDuration(700);
        anim.start();
    }

}

Bước 3: Chỉnh style cho dialog (style.xml)

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="MyAlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">

        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:windowBackground">@color/colorAccent</item>
    </style>
</resources>

Cuối cùng là toàn bộ source code cho bài viết hướng dẫn này:

Trên đây là những bước tạo dialog trong android với hiệu ứng đẹp mắt. Nếu bạn có bất cứ câu hỏi nào, đừng ngại để lại comment bên dưới phần bình luận!

Đừng quên like và share nữa nha!

💦 Đọc thêm bài viết hướng dẫn Android:

Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trướcQuản lý State với React Hooks – Không cần Redux hay Context API
Bài tiếp theoBỏ từ khóa else trong hàm if. Có nên không?
Sơn Dương
Tên đầy đủ là Dương Anh Sơn. Tốt nghiệp ĐH Bách Khoa Hà Nội. Mình bắt đầu nghiệp coder khi mà ra trường chẳng xin được việc đúng chuyên ngành. Mình tin rằng chỉ có chia sẻ kiến thức mới là cách học tập nhanh nhất. Các bạn góp ý bài viết của mình bằng cách comment bên dưới nhé !

1
Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Mới nhất Cũ nhất Nhiều voted nhất
Thông báo
Lộc
Guest
Lộc

Nhìn hiệu ứng này cũng tạm đc. Hì