본문 바로가기
안드로이드 자바

[JAVA][Android] CoordinatorLayout과 BottomSheet 사용해서 유투브 화면 따라 만들기(1)

by teamnova 2024. 7. 26.
728x90

 

안녕하세요.

CoordinatorLayout과 BottomSheet를 사용해서 다음 동영상의 유투브 화면을 따라만들기 예제입니다.

먼저 오늘은 동영상 플레이어와 동영상 정보를 보여주는 바텀시트를 먼저 만들어보겠습니다.

 

 

1. Media3 ExoPlayer 의존성 추가

먼저 앱수준 build.gradle에 동영상 플레이어를 사용하기 위한 Media3 ExoPlayer 의존성을 최신버전으로 추가합니다.

implementation "androidx.media3:media3-exoplayer:1.4.0"
implementation "androidx.media3:media3-exoplayer-dash:1.4.0"
implementation "androidx.media3:media3-ui:1.4.0"

 

 

2. 바텀시트 배경 drawble 만들기

바텀시트를 둥근 모서리로 만들기 위해 drawble 폴더에 다음과 같이 xml 파일을 만듭니다.

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

 

 

3. 메인 액티비티 레이아웃 작성하기

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/coordinator_layout"
    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"
    tools:context=".MainActivity"
    android:background="@color/black">

    <!-- 동영상 뷰 -->
    <androidx.media3.ui.PlayerView
        android:id="@+id/player_view"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_gravity="top"
        app:use_controller="true"
        app:resize_mode="fit"/>

    <!-- 정보 Bottom Sheet -->
    <LinearLayout
        android:id="@+id/info_bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="16dp"
        android:background="@drawable/white_round_top_border_20"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
        app:behavior_hideable="true"
        app:behavior_peekHeight="360dp">

        <!-- 드래그 핸들 -->
        <com.google.android.material.bottomsheet.BottomSheetDragHandleView
            android:id="@+id/drag_handle_info"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="동영상 제목"
            android:textSize="18sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="영상에 대한 설명 ~~"
            android:layout_marginTop="8dp" />

        <Button
            android:id="@+id/button_show_comments"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="댓글 보기"
            android:layout_marginTop="16dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="관련된 영상\n광고\n그외 기타등등\n"
            android:layout_marginTop="8dp" />
    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

 

 

4. 메인 액티비티 작성하기

import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.media3.common.MediaItem;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.ui.PlayerView;
import com.google.android.material.bottomsheet.BottomSheetBehavior;

public class MainActivity extends AppCompatActivity {

    private BottomSheetBehavior<View> infoBottomSheetBehavior;
    private PlayerView playerView;
    private ExoPlayer player;
    private GestureDetector gestureDetector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // ExoPlayer 초기화
        playerView = findViewById(R.id.player_view);
        player = new ExoPlayer.Builder(this).build();
        playerView.setPlayer(player);

        // 동영상 설정
        MediaItem mediaItem = MediaItem.fromUri("https://www.example.com/video.mp4"); // 재생할 동영상 주소
        player.setMediaItem(mediaItem);
        player.prepare();
        player.play();

        // 정보 Bottom Sheet 설정
        View infoBottomSheet = findViewById(R.id.info_bottom_sheet);
        infoBottomSheetBehavior = BottomSheetBehavior.from(infoBottomSheet);
        infoBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);

        // GestureDetector 초기화 및 설정
        gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                // 위로 스와이프하면 정보 Bottom Sheet를 다시 확장
                if (e2.getY() < e1.getY()) {
                    if (infoBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_HIDDEN) {
                        infoBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                    }
                }
                return super.onFling(e1, e2, velocityX, velocityY);
            }
        });

        // 정보 Bottom Sheet 상태 변화 감지
        infoBottomSheetBehavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) playerView.getLayoutParams();
                if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                    // 정보 Bottom Sheet가 숨겨졌을 때 동영상 뷰를 화면 가운데로 이동
                    params.gravity = android.view.Gravity.CENTER_VERTICAL;
                    // 스크린 전체에서 터치 이벤트를 감지하여 GestureDetector에 전달
                    findViewById(R.id.coordinator_layout).setOnTouchListener(new View.OnTouchListener() {
                        @Override
                        public boolean onTouch(View v, MotionEvent event) {
                            gestureDetector.onTouchEvent(event);
                            return true;
                        }
                    });
                } else {
                    // 정보 Bottom Sheet가 보일 때 동영상 뷰를 위로 밀기
                    params.gravity = android.view.Gravity.TOP;
                    // 터치 이벤트 해제
                    findViewById(R.id.coordinator_layout).setOnTouchListener(null);
                }
                playerView.setLayoutParams(params);
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                // 필요한 경우 슬라이드 동작에 따라 애니메이션을 추가할 수 있습니다.
            }
        });


    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        player.release(); // ExoPlayer 자원 해제
    }
}

 

 

5. 시연영상

위 코드를 실행하면 다음과 같이 영상 정보 바텀시트가 사라지고 나타남에 따라 동영상 플레이어의 위치가 변경되는 것을 확인 할 수 있습니다.

 

 

 

 


 

다음 시간에는 댓글보기 버튼을 클릭시 댓글을 확인할 수 있는 바텀시트를 볼 수 있도록 구현해보겠습니다.

감사합니다~