Android App

mediaPlayer+surfaceView, 동영상 소형플레이어 기본모드 전환 in Android Studio

YunSeong 2021. 9. 4. 14:34
728x90
반응형

유튜브 앱처럼 동영상을 기본 모드와 소형 플레이어로 전환을 할 수 있고 pip모드처럼 소형 플레이어를 원하는 대로 배치할 수 있도록 했다.

하지만 이때 동영상을 구현할 때 videoView를 사용하면 오류가 나서 surfaceView를 사용했다.

1. activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?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"
    tools:context=".MainActivity"
    android:id="@+id/relativeLayout">
    <Button
        android:id="@+id/startButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="86dp"
        android:layout_marginTop="645dp"
        android:text="start" />
    <Button
        android:id="@+id/stopButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="243dp"
        android:layout_marginTop="645dp"
        android:text="stop" />
    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="400px"
        android:layout_height="200px"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="111dp"
        android:layout_marginTop="217dp">
        <SurfaceView
            android:id="@+id/surfaceView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
</RelativeLayout>
cs

2, 31~34 - surfaceView를 원하는 곳에 배치하기 위해서 자유도가 높은 relativeLayout을 사용했고 layout_margin을 이용해서 위치를 설정할 것이다.


2. MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package com.example.mediaplayervideoviewexamplewithrelativelayout;
 
import ...
 
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
 
    RelativeLayout relativeLayout;
 
    LinearLayout linearLayout;
 
    int lastY, lastX, curY, curX;
 
    int mpWidth;
    int mpHeight;
 
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    MediaPlayer mediaPlayer;
 
    boolean isPIPMode = true;
    boolean lastIsPIPMode = true;
 
    Button startButton, stopButton;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        relativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout);
 
        linearLayout = (LinearLayout)findViewById(R.id.linearLayout);
 
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(400200);
        layoutParams.setMargins(10010000);
        linearLayout.setLayoutParams(layoutParams);
 
        relativeLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = event.getAction();
 
                if (layoutParams.topMargin <= 10){ //surfaceView를 위로 올렸을 때 이벤트를 설정한다.
                    isPIPMode = false;
                    RelativeLayout.LayoutParams notPIPLayoutParams = new RelativeLayout.LayoutParams(mpWidth, mpWidth/2); //크기를 꽉차게 만들어준다.
                    notPIPLayoutParams.setMargins(0000); //제일 위에 배치시켜준다.
                    linearLayout.setLayoutParams(notPIPLayoutParams);
                    lastIsPIPMode = isPIPMode;
                } else {
                    isPIPMode = true;
                    linearLayout.setLayoutParams(layoutParams);
                    if (!lastIsPIPMode){ //mode가 바꼈을 때 터치하고 있는 위치로 소형 플레이어를 이동시킨다.
                        layoutParams.setMargins((int)event.getX() - 200, (int)event.getY() - 10000);
                    }
                    lastIsPIPMode = isPIPMode;
                }
 
                if (action == MotionEvent.ACTION_DOWN) { //Margin에 좌표의 편차를 더해줘서 드레그하는 손에 따라서 소형 플레이어가 움직이도록 한다.
                    lastY = (int) event.getY();
                    lastX = (int) event.getX();
                } else if(action == event.ACTION_MOVE && ((layoutParams.leftMargin < lastX && lastX < layoutParams.leftMargin + (isPIPMode?400:mpWidth)) && (layoutParams.topMargin < lastY && lastY < layoutParams.topMargin + (isPIPMode?400:mpWidth)/2))){
                    curY = (int)event.getY();
                    curX = (int)event.getX();
                    if ((layoutParams.leftMargin + (isPIPMode?400:mpWidth) >= mpWidth && curX - lastX <= 0|| (layoutParams.leftMargin <= 0 && curX - lastX >= 0|| (layoutParams.leftMargin + (isPIPMode?400:mpWidth) < mpWidth && layoutParams.leftMargin > 0))
                    {
                        layoutParams.setMargins(layoutParams.leftMargin + curX - lastX, layoutParams.topMargin, 00);
                        linearLayout.setLayoutParams(layoutParams);
                    }
                    if ((layoutParams.topMargin + (isPIPMode?400:mpWidth)/2 >= mpHeight && curY - lastY <= 0|| (layoutParams.topMargin <= 0 && curY - lastY >= 0|| (layoutParams.topMargin + (isPIPMode?400:mpWidth)/2 < mpHeight && layoutParams.topMargin >0))
                    {
                        layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + curY - lastY, 00);
                        linearLayout  .setLayoutParams(layoutParams);
                    }
                    lastX = curX;
                    lastY = curY;
                }
                return true;
            }
        });
 
        surfaceView = (SurfaceView)findViewById(R.id.surfaceView);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
 
        startButton = (Button)findViewById(R.id.startButton);
        startButton.setOnClickListener(v -> {
            if (!mediaPlayer.isPlaying()){
                mediaPlayer.start();
            }
        });
 
        stopButton = (Button)findViewById(R.id.stopButton);
        stopButton.setOnClickListener(v -> {
            if (mediaPlayer.isPlaying()){
                mediaPlayer.stop();
 
                try {
                    mediaPlayer.prepare();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
 
    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
        if (mediaPlayer == null) {
            mediaPlayer = new MediaPlayer();
        } else {
            mediaPlayer.reset();;
        }
 
        try {
            Uri uri = Uri.parse("android.resource://" + getPackageName() + "/raw/video");
            mediaPlayer.setDataSource(this, uri);
            mediaPlayer.setDisplay(surfaceHolder);
            mediaPlayer.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int formatint width, int height) { }
 
    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) { }
 
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        mpWidth = relativeLayout.getWidth();
        mpHeight = relativeLayout.getHeight();
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null){
            mediaPlayer.release();
        }
    }
}
cs

3. 결과

 

 

 

728x90
반응형