개발새발 - IT 기술블로그
article thumbnail

안녕하세요. 이번 포스팅에서는 특정 이벤트를 발생시켰을 때 앱 하단에서 커스텀 다이얼로그가 올라오는 기능을 구현해 보도록 하겠습니다.

이번에도 코드부터 보여드려야죠😃 

 

+ 참고로 다이얼로그의 모서리를 둥글게 만드는 코드는 아래 설명부분에 있습니다!

 

 

 

결과 GIF🎬

 

결과코드👀

BottomSheetFragmentDialog는 material 라이브러리에서 제공하므로 implement 해줍니다.

 프로젝트를 생성하면 기본으로 되어있으니 없는분들만 추가해주시면 될 것 같습니다.

implementation 'com.google.android.material:material:1.7.0'

 

 

MainActivity의 xml에서는 이벤트를 발생시킬 버튼 한개를 생성해주시면 됩니다. 코드는 생략하겠습니다.

 

XML

<fragment_bottom_sheet.xml>

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
    tools:context=".BottomSheetFragment">

    <ImageView
        android:id="@+id/bottom_img"
        android:layout_width="75dp"
        android:layout_height="75dp"
        android:layout_marginStart="15dp"
        android:layout_marginTop="15dp"
        android:layout_marginBottom="10dp"
        android:src="@drawable/image"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/bottom_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="15dp"
        android:layout_marginTop="10dp"
        android:text="Title"
        android:textAllCaps="false"
        android:textColor="@color/black"
        android:textSize="17sp"
        app:layout_constraintStart_toEndOf="@+id/bottom_img"
        app:layout_constraintTop_toTopOf="@+id/bottom_img" />

    <TextView
        android:id="@+id/bottom_link"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:ellipsize="end"
        android:lines="1"
        android:text="URL"
        android:textSize="13sp"
        app:layout_constraintStart_toStartOf="@+id/bottom_title"
        app:layout_constraintTop_toBottomOf="@+id/bottom_title" />

    <ImageView
        android:id="@+id/bottom_right"
        android:layout_width="35dp"
        android:layout_height="35dp"
        android:layout_marginEnd="20dp"
        android:src="@drawable/right"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:tint="@color/black" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

Kotlin

 <BottomSheetFragment.kt>

package com.example.bottomsheetdialogeaxm

import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import com.google.android.material.bottomsheet.BottomSheetDialogFragment

class BottomSheetFragment : BottomSheetDialogFragment() {
    private val url: String = "https://tekken5953.tistory.com/"		// 이동할 URL주소
    private val title: String = "devJaeYL's Tistory blog"		// 타이틀 메시지

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_bottom_sheet, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val link: TextView = view.findViewById(R.id.bottom_link)
        val name: TextView = view.findViewById(R.id.bottom_title)
        link.text = url
        name.text = title

        view.setOnClickListener {
            dismiss()
            val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
            val chooser = Intent.createChooser(intent, "Open With")
            try {
                startActivity(chooser)
            } catch (e: ActivityNotFoundException) {
                Log.e(javaClass.name, "Link error is $e")
                Toast.makeText(context, "링크로 이동할 수 없습니다", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

<MainActivity.kt>

val btn: Button = findViewById(R.id.showDialogBtn)

btn.setOnClickListener{
    val bottomSheet = BottomSheetFragment()
    bottomSheet.show(supportFragmentManager, bottomSheet.tag)
}

 

Java

<BottomSheetFragment.java>

package com.example.bottomsheetdialogeaxm;

import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.material.bottomsheet.BottomSheetDialogFragment;

public class BottomSheetFragmentJava extends BottomSheetDialogFragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        final String linkStr = "https://tekken5953.tistory.com/";	// 이동할 URL 주소
        final String titleStr = "devJaeYL's Tistory blog";		// 타이틀 메시지

        TextView linkText = view.findViewById(R.id.jbottom_link);
        TextView titleText = view.findViewById(R.id.jbottom_title);

        linkText.setText(linkStr);
        titleText.setText(titleStr);

        view.setOnClickListener(v -> {
            dismiss();
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(linkStr));
            Intent chooser = Intent.createChooser(intent, "Open With");

            try {
                startActivity(chooser);
            } catch (ActivityNotFoundException e) {
                Log.e(getClass().getSimpleName(), "Link error is " + e);
                Toast.makeText(getContext(), "링크로 이동할 수 없습니다", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

<MainActivity.java>

Button button = findViewById(R.id.showDialogBtn);

button.setOnClickListener(v -> {
	BottomSheetFragmentJava bottomSheetFragment = new BottomSheetFragmentJava();
	bottomSheetFragment.show(getSupportFragmentManager(), bottomSheetFragment.getTag());
});

 


 

그럼 코드에 대해 알아보겠습니다. 

 

 

메인 엑티비티에서 버튼을 클릭하면 프래그먼트를 생성하고 다이얼로그를 보여주는 부분입니다.

bottomSheet.show 메서드에 프래그먼트 매니저와 태그를 입력하고 호출하면 다이얼로그가 생성됩니다. 

val bottomSheet = BottomSheetFragment()
bottomSheet.show(supportFragmentManager, bottomSheet.tag)

 

 

프래그먼트의 onCreateView에서 view(다이얼로그)를 클릭 했을 때 이벤트를 처리하는 부분입니다.

view.setOnClickListener{
	…
}

 

 

Intent.ACTION_VIEW를 사용하여 암시적 인텐트로 url 링크를 새창으로 띄웁니다.

val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))

 

 

createChooser는 링크를 열 앱이 2개이상일 경우 사용자가 선택하게 하는 메서드입니다.

현재 프래그먼트가 액티비티를 가지고 있다면 새 창을 열어 링크를 시작합니다.

val chooser = Intent.createChooser(intent, "Open With")
try {
       	startActivity(chooser)
     } catch (e: ActivityNotFoundException) {
      	Log.e(javaClass.name, "Link error is $e")
      	Toast.makeText(context, "링크로 이동할 수 없습니다", Toast.LENGTH_SHORT).show()
	}

 

 

추가로 다이얼로그의 모서리부분을 둥글게 만드는 radius설정에 대해 알아보겠습니다.

 

drawable 폴더에 아래 파일을 추가해줍니다. 저는 bottom_radius라고 만들었습니다.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:topLeftRadius="10dp"
        android:topRightRadius="10dp"/>
    <solid android:color="@color/white"/>
</shape>

 

 

<themes.xml>

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.BottomSheetDialogEaxm" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
   		…
    <item name="bottomSheetDialogTheme">@style/AppBottomSheetDialogTheme</item>
    </style>
    
    	…
    
    <style name="AppBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="bottomSheetStyle">@style/AppModalStyle</item>
    </style>
        
    <style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal">
        <item name="android:background">@drawable/bottom_radius</item>
    </style>
    
    </resources>

 

이상으로 BottomSheetFragmentDialog의 사용법에 대해 알아보았습니다.

 

이 예제 이외에도 본인이 필요한 방식으로 클래스에서 커스텀이 가능하니 유용할 듯 합니다.

 

감사합니다.

 

 

 

참고

https://youngest-programming.tistory.com/349

 

[안드로이드] 안드로이드 BottomSheetDialog 콜백 구현

[2021-04-14 업데이트] 가장 하단에 PS 부분에 변경 후 코드를 참고해주세요 :) 최신코드입니다. 본 프로젝트 전에 적용하기 전 샘플 프로젝트로 잘 되나 바텀시트다이얼로그를 테스트해봤습니다.

youngest-programming.tistory.com

 

 

예제 소스

https://github.com/tekken5953/BottomSheetDialogEaxm

 

GitHub - tekken5953/BottomSheetDialogEaxm

Contribute to tekken5953/BottomSheetDialogEaxm development by creating an account on GitHub.

github.com