안녕하세요.
오늘은 스크롤뷰 안에서 드래그 앤 드롭을 사용하는 방법에 대하여 알아보겠습니다.
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에서 드래그 앤 드롭을 사용하는 방법에 대해 알아보았습니다.
궁금한 점은 언제든지 댓글로 질문해주세요.
감사합니다.
'안드로이드 자바' 카테고리의 다른 글
[Java][Android] 화면 꺼지지 않게 하기(켜짐 상태 유지) (2) | 2022.09.13 |
---|---|
[Java][Android] 화면이 회전 되었을 때 이전 액티비티의 데이터 유지하기 (0) | 2022.08.29 |
[JAVA][Android] 동적으로 생성한 View를 삭제하기 (0) | 2022.08.02 |
[JAVA][Android] 동적으로 View 여러 개 추가 후 해당 View 드래그 앤 드랍으로 이동시키기 (0) | 2022.07.18 |
[java][android] 다이얼로그에서 수정한 값 액티비티로 가져오기 (0) | 2022.07.14 |