안녕하세요. 학교다니면서 궁금한건 이곳에 묻고 아는건 나누고 했는데 개발자 정보 게시판에 글을 적는건 처음이네요 ^^
얼마전 왼쪽기준과 오른쪽기준으로 화면이 두개가 필요한 상황이 생겼습니다.
그래서 왼쪽기준으로 화면을 만들고 오른쪽 기준은 레이아웃 자체를 좌우반전하고 싶은 상황이 왔습니다.
그런데 구글링을 해봐도 레이아웃 좌우반전하는 방법이 나오지를 않더라구요.
그래서 방법을 찾아서 혹시 필요하신 분이 계실까 이렇게 글을 적어봅니다.
제가 만들 화면은 아래 그림의 상단과 같은 화면에서
-파랑색 배경 : 화면이 좌우 반전되어야 하는 곳(좌측과 우측기준에 따라)
-검정색 배경 : 화면이 좌우 반전없이 고정되는 곳
※상하 두 화면 중 위의 화면<그림1>은 좌측 기준으로 그려진것이고,
아래 화면<그림2>은 좌측기준 화면의 하얀 레이아웃을 좌우반전한 것입니다.
<그림1>
<그림2>
찾기 실패해서 당황하고 있었는데 조금만 생각해보니 꽤 쉽게 해결이 되었습니다.
일단 할 일을 요약하면 좌우반전이 필요한 부분의 최상위 레이아웃을 커스터마이징 하는 것입니다.
모든 뷰들은 폴더구조로 최상위부터 자식뷰들을 가지는 트리구조로 되어있습니다.
그래서 (이부분은 제 추측 시작...) 액티비티에서 화면을 그릴 자원(이하 canvas)을 최상위 뷰에게 전달하면
최상위 뷰는 자신의 영역을 그리고 자식 뷰들에게 canvas를 전달하여 각자 자기를 그리도록 하는 구조입니다.(제 추측 끝...)
여기서 canvas를 사용하여 호출하는 부분이 Draw(Canvas c)함수와 dispatchDraw(Canvas c)함수입니다.
Draw는 자신을, dispatchDraw는 자식을 그리는 함수로 예측됩니다.(아니라면 댓글 주시면 수정하겠습니다.)
그래서 이 dispatchDraw함수를 오버라이드해서 canvas의 matrix를 사용하여 좌우반전을 설정해주면 나의 자식노드들은 좌우 반전되어
그려지게 됩니다.
커스터마이징 한 클래스는 아래와 같습니다.
1. 아래와 같이 클래스를 만듭니다.
- ReverseAbleRelativeLayout .java -
package com.reverse; import android.content.Context; import android.graphics.Canvas; import android.graphics.Matrix; import android.util.AttributeSet; import android.widget.RelativeLayout; public class ReverseAbleRelativeLayout extends RelativeLayout { private boolean isReverse = false; public boolean isReverse() { return isReverse; } public void setReverse(boolean isReverse) { this.isReverse = isReverse; } public ReverseAbleRelativeLayout(Context context) { super(context); } public ReverseAbleRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } public ReverseAbleRelativeLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void dispatchDraw(Canvas arg0) { if(isReverse){ Matrix matrix = arg0.getMatrix(); matrix.setScale(-1, 1, arg0.getWidth()/2, arg0.getHeight()/2); arg0.setMatrix(matrix); } super.dispatchDraw(arg0); } }
여기서 중요한 부분은 matrix.setScale(-1, 1, arg0.getWidth()/2, arg0.getHeight()/2)입니다.
여기서 상하반전을 해야 할 경우setScale(1, -1, width/2, height/2) 로 하시면 됩니다.
2. 아래와 같이 화면을 만듭니다.
- activity_main.xml -
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.reverse.ReverseAbleRelativeLayout android:id="@+id/reverse_layer" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#88123456" > </com.reverse.ReverseAbleRelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="150dp" android:background="#33772233"> </RelativeLayout> </LinearLayout>
3. 컴파일을 합니다!
4. MainActivity를 아래와 같이 수정하여 다시 컴파일 합니다.
- MainActivity.java -
package com.reverse; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((ReverseAbleRelativeLayout)findViewById(R.id.reverse_layer)).setReverse(true); } }
((ReverseAbleRelativeLayout)findViewById(R.id.reverse_layer)).setReverse(true); 를 설정하여 좌우 반전 여부를
설정할 수 있습니다.
main_activity.xml의 내부에 여러 View들을 넣어서 컴파일 할 경우 3번 결과가 그림1이며, 4번 결과가 그림2와 같습니다.
혹시 구글링 해서 안나오시는 분은 참고하시면 될 것 같습니다.
간단하지만 제가 테스트하면서 작성한 프로젝트 첨부합니다!이상 저임ㅋ였습니다.
(코드하이라이트 쓰는게 잘 안되네요..)
오우...감사합니다.