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

[JAVA][Android] ScrollView안에서 드래그 앤 드롭 사용하기

by teamnova 2022. 8. 14.
728x90

안녕하세요.

오늘은 스크롤뷰 안에서 드래그 앤 드롭을 사용하는 방법에 대하여 알아보겠습니다.

 

https://stickode.tistory.com/511

(해당 포스트와 이어집니다.)

 

그냥 드래그 앤 드롭 구현하듯이 onTouchListener로 구현하면 되는거 아니냐 라고 하실 수 있는데

 

 

 

위 영상을 보시면 알겠지만 스크롤 뷰 안에 그냥 드래그 앤 드롭을 구현 시

ScrollView의 스크롤 이벤트와

드래그 앤 드롭의 터치 이벤트가 겹쳐 잘 실행되지 않게 됩니다.

 

그럼 시작하겠습니다.

 

일단 xml파일을 수정해줍니다.

 

<!-- test.xml -->

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/addButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="버튼 추가"
            android:layout_weight="50"/>
        <Button
            android:id="@+id/removeButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="버튼 삭제"
            android:layout_weight="50"/>
    </LinearLayout>

    <ScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/dynamicArea"
            android:layout_width="match_parent"
            android:layout_height="2000dp"
            android:orientation="vertical"
            >

            <View
                android:id="@+id/layout_end"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="2000dp"
                app:layout_constraintTop_toTopOf="parent"
                tools:ignore="MissingConstraints" />

        </androidx.constraintlayout.widget.ConstraintLayout>
    </ScrollView>

</LinearLayout>

스크롤 뷰를 사용해 ConstraintLayout을 감싼것을 확인할 수 있습니다.

 

다음으로 자바 파일입니다.

 

저번에 제작한 파일에서 LinearLayout 부분을 ConstraintLayout으로 전부 바꿔주시고요.

 

java 파일에서 스크롤뷰를 선언해 findViewId를 해줍니다.

 

//MainActivity.java

public class MainActivity extends Activity implements View.OnTouchListener {

    ScrollView myScroll; // 스크롤뷰 선언

    private ConstraintLayout dynamicLayout; // 버튼이 생성될 공간
.
.
.

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

    myScroll = findViewById(R.id.scroll);

이제 드래그 앤 드롭이 실행되는 onTouch 메소드입니다.

onTouch가 처음 동작할 때

@Override
public boolean onTouch(View v, MotionEvent event) { // 버튼을 드래그 앤 드랍하는 메소드(OnTouchListener)
    int width = ((ViewGroup) v.getParent()).getWidth() - v.getWidth();
    int height = ((ViewGroup) v.getParent()).getHeight() - v.getHeight();

    myScroll.requestDisallowInterceptTouchEvent(true);

위와 같이 myScroll.requestDisallowInterceptTouchEvent(true); 를 선언해 줍니다.

 

그리고 드래그 앤 드롭(터치 이벤트)이 끝나는 시점인 ACTION_UP 부분에서

} else if (event.getAction() == MotionEvent.ACTION_UP) {
    myScroll.requestDisallowInterceptTouchEvent(false);
    if (v.getX() > width && v.getY() > height) {

myScroll.requestDisallowInterceptTouchEvent(false);를 선언해줍니다.

 

여기서 사용한 requestDisallowInterceptTouchEvent는 부모에게 터치 이벤트를 빼앗기지 않게 해주는 역할을 하는데요,

스크롤 이벤트 또한 터치 이벤트로 인식이 되기 때문에 requestDisallowInterceptTouchEvent를 사용하였습니다.

OnTouch(드래그 앤 드롭)가 시작될 때 requestDisallowInterceptTouchEvent를 true로 선언해주고,

드래그 앤 드롭이 끝나는 시점인 ACTION_UP 부분에서 다시 requestDisallowInterceptTouchEvent를 false로 선언해

드래그 앤 드롭이 끝나면 정상적으로 스크롤을 할 수 있는 것 입니다.

이제 해당 코드를 실행 시켜보도록 하겠습니다!

 

 

보시는 것과 같이 onTouchListener가 세팅된 버튼을 드래그 앤 드롭 할 때는 스크롤뷰가 실행되지 않고,

그 외 바탕을 클릭하여 스크롤하면 스크롤뷰가 실행되는 것을 보실 수 있습니다.

 

오늘은 이렇게 ScrollView에서 드래그 앤 드롭을 사용하는 방법에 대해 알아보았습니다.

 

궁금한 점은 언제든지 댓글로 질문해주세요.

감사합니다.