반응형

 

 

어떻게 사용하는지 알기 어려웠던 컨스트레인트 레이아웃에 조금 친숙해진 기념으로 만든 영상입니다. 

다음 순으로 영상이 올라가게 됩니다.  

 

도움이 되었으면 좋아요와 구독을 해주세요. 
감사합니다.

 

컨스트레인트 레이아웃은 부모뷰와 자식뷰에 붙이는 Left, Right, Top, Bottom을 숙지한다면 쉽게 이해할 수 있습니다. 

자세한 내용은 영상에서 확인하세요.  컨스트레인트 레이아웃에 익숙해지도록 반복적으로 말하는 것을 염두하고 보세요. 

 

 


1. 안드로이드 강좌 - 컨스트레인트 레이아웃을 사용해보자 1/3(Constraint Layout)

# 컨스트레인트 레이아웃 기본 개념



2. 안드로이드 강좌 - 컨스트레인트 레이아웃을 사용해보자 2/3(Constraint Layout)

# 가로 방향으로 자식뷰 배치
# ChainStyle
# Bias
# Weight

 

 


3. 안드로이드 강좌 - 컨스트레인트 레이아웃을 사용해보자 3/3(Constraint Layout)

# 세로 방향으로 자식뷰 배치
# baseline constraint
# march_constraint 
# ChainStyle
# Bias
# Weight

 



4. 가이드라인(Guideline)과 배리어(Barrier)에 대해서는 본 포스트에 작성되어 있습니다. 

 

Guideline

 

UI 컴포턴트에 대한 제약 조건을 추가할때 원하는 위치에 배치한 가이드라인을 사용할 수 있습니다. 

가이드라인은 실행시에는 보이지 않고 UI 편집시에만 보이는 선입니다. 

 

 

다음 3가지 방식으로 가이드라인을 레이아웃에 추가할 수 있습니다.

 

layout_constraintGuide_begin

수평방향(Left), 수직방향(Top)으로부터 지정한 dp만큼  떨어진 곳에 가이드라인을 위치시킵니다. 

 

layout_constraintGuide_end

수평방향(Right), 수직방향(Bottom)으로부터 지정한 dp만큼 떨어진 곳에 가이드라인을 위치시킵니다.  

 

app:layout_constraintGuide_percent

수평방향(Left), 수직방향(Top)으로부터 지정한 퍼센트만큼 떨어진 곳에 가이드라인을 위치시킵니다. 



다음 예제는 Left로부터 100dp 떨어진 곳에 수직 가이드라인을, Top에서부터 400dp 떨어진 곳에 수평 가이드라인을 추가한 예제입니다. 

 

이미지와 텍스트뷰, 에디트텍스트를 아래 그림처럼 배치해보았습니다. 

 

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintBottom_toTopOf="@+id/guideline1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_begin="400dp" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="100dp" />


    <TextView
        android:id="@+id/textview1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="30dp"
        android:text="Name"
        android:textSize="20sp"
        android:textAlignment="center"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/guideline1" />


    <EditText
        android:id="@+id/edittext1"
        android:layout_marginStart="30dp"
        android:layout_marginEnd="30dp"
        app:layout_constraintLeft_toRightOf="@+id/textview1"
        app:layout_constraintTop_toBottomOf="@id/guideline1"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_width="0dp"
        android:layout_height="wrap_content"/>

</androidx.constraintlayout.widget.ConstraintLayout>


Barrier

 

배리어도 가이드라인과 같은 용도로 사용되지만 차이가 있습니다. 
가이드라인은 지정한 위치에 고정되는 반면 배리어는 UI의 크기가 변하면 그에따라 위치가 동적으로 변경됩니다. 

 

예를 들어 아래처럼 TextView의 크기가 변함에 따라 배리어의 위치도 변합니다. 

 

초기에 배치된 배리어입니다. 

 

오른쪽에 있는 텍스트뷰의 크기가 변하자 배리어가 아래쪽으로 이동한 것을 볼 수 있습니다. 

 

UI를 확인후. right_text_view의 텍스트를 두배로 늘려보세요.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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">

    <TextView
        android:id="@+id/left_text_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:text="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        android:textSize="16sp"
        android:background="#efdca4"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/right_text_view"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/right_text_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:text="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        android:textSize="16sp"
        android:background="#9cd0b3"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/left_text_view"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="left_text_view,right_text_view" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/barrier" />

</androidx.constraintlayout.widget.ConstraintLayout>

 


가이드라인은 아래 예제처럼 UI 컴포넌트의 크기가 변하더라도 가이드라인의 위치가 변하지 않습니다.

 

초기 상태

 

 

텍스트뷰 크기가 증가한 후

텍스트뷰의 크기는 커졌는데 가이드라인이 그대로라 텍스트뷰가 화면 바깥으로 벗어났습니다.



UI를 확인후. right_text_view의 텍스트를 두배로 늘려보세요.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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">

    <TextView
        android:id="@+id/left_text_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:text="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        android:textSize="16sp"
        android:background="#efdca4"
        app:layout_constraintBottom_toTopOf="@+id/guideline"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/right_text_view"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/right_text_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:text="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        android:textSize="16sp"
        android:background="#9cd0b3"
        app:layout_constraintBottom_toTopOf="@+id/guideline"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/left_text_view"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline" />


    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.2" />

</androidx.constraintlayout.widget.ConstraintLayout>


참고

 

https://medium.com/@futureofdev/android-constraintlayout-%EC%89%BD%EA%B2%8C-%EC%95%8C%EC%95%84%EA%B0%80%EC%9E%90-62d2ded79c17

 

https://stackoverflow.com/a/47241263

 

https://medium.com/@alancamargo92/the-ultimate-view-group-constraintlayout-e0598d2e1a05



 

 

반응형

포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

여러분의 응원으로 좋은 컨텐츠가 만들어집니다.
지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요.

  1. Favicon of https://hw00173.tistory.com BlogIcon hw00173 2019.12.14 22:45 신고

    안녕하세요.

    개발 도중 constraintLayout과 관련되어 문제를 해결하지 못해 질문을 드립니다.!!

    제가 구현하고자 하는 것은 동적으로 View 생성한 뒤 생성 된 동적뷰를 터치리스너를 통해 이동 시키거나 한 뒤
    Long Click 하여 다른 TextView나 Button 등이 해당 동적뷰를 기준으로 옆에 정렬 되게끔 하고 싶습니다.
    처음 동적뷰를 constraintLayout 에서 생성 되는 것까진 했으나, 해당 뷰 옆에 다른 뷰가 정렬 시키는 부분에서 잘 해결 되지 않고 있습니다.!

    아래 제 코드 첨부하도록 하겠습니다.

    도움부탁드리겠습니다.! 감사합니다.

    public class Fit_Me_page extends AppCompatActivity implements View.OnTouchListener, View.OnLongClickListener {


    private RecyclerView fit_me_recyclerview;

    private ArrayList<Fit_Me_Array> fit_me_arrays;

    private Fit_Me_Adapter fit_me_adapter;

    Fit_Me_Category_Array fit_me_category_array;

    int category_number = 0;

    ConstraintLayout fit_me_constraintLayout;

    private ConstraintSet applyConstraintSet = new ConstraintSet();

    TextView textView, textView2;

    ImageView imageView;
    ImageView testview;

    int i = 11;
    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_fit_me_page);




    fit_me_recyclerview = findViewById(R.id.fit_me_recyclerview);

    //그리드뷰형 리사이클러뷰를 사용하기 위한 매니저 객체
    GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);

    fit_me_arrays = new ArrayList<>();

    fit_me_adapter = new Fit_Me_Adapter(this, fit_me_arrays);

    fit_me_recyclerview.setAdapter(fit_me_adapter);

    fit_me_recyclerview.addItemDecoration(new grid_view_padding(this));

    fit_me_recyclerview.setLayoutManager(gridLayoutManager);

    fit_me_constraintLayout = findViewById(R.id.fit_me_ConstraintLayout);

    textView = findViewById(R.id.textView5);
    textView2 = findViewById(R.id.textView2);


    textView.setOnTouchListener(this::onTouch);

    textView2.setOnTouchListener(this::onTouch);

    fit_me_category_array = new Fit_Me_Category_Array();





    for (int i =0; i<fit_me_category_array.category_all().size(); i++){


    Fit_Me_Array fit_me_array = new Fit_Me_Array(fit_me_category_array.category_all().get(i));
    fit_me_arrays.add(fit_me_array);

    }

    fit_me_adapter.notifyDataSetChanged();


    fit_me_adapter.setOnItemClickListener(new Fit_Me_Adapter.OnItemClickListener() {
    @Override
    public void onItemClick(int position) {



    imageView = new ImageView(Fit_Me_page.this);


    imageView.setImageResource(R.drawable.color_wheel);

    // imageView.setLayoutParams(layoutParams);

    imageView.bringToFront();

    imageView.setOnTouchListener(Fit_Me_page.this::onTouch);

    imageView.setOnLongClickListener(Fit_Me_page.this::onLongClick);

    i++;

    imageView.setId(i);

    imageView.setTag("가가가");


    fit_me_constraintLayout.addView(imageView);



    applyConstraintSet.clone(fit_me_constraintLayout);
    applyConstraintSet.connect(imageView.getId(), ConstraintSet.TOP, fit_me_constraintLayout.getId(), ConstraintSet.TOP, 460);

    Log.d("imageView_id", "onItemClick:"+imageView.getId());
    applyConstraintSet.connect(textView2.getId(), ConstraintSet.LEFT, imageView.getId(), ConstraintSet.RIGHT, 10);

    applyConstraintSet.connect(textView2.getId(), ConstraintSet.TOP, imageView.getId(), ConstraintSet.TOP, 10);

    applyConstraintSet.applyTo(fit_me_constraintLayout);





    });

    }

    float oldXvalue;

    float oldYvalue;

    @Override
    public boolean onTouch(View v, MotionEvent event){

    int parentWidth = ((ViewGroup)v.getParent()).getWidth(); // 부모 View 의 Width
    int parentHeight = ((ViewGroup)v.getParent()).getHeight(); // 부모 View 의 Height

    if(event.getAction() == MotionEvent.ACTION_DOWN){
    // 뷰 누름
    Log.d("바로?", "onTouch: "+"다운");
    oldXvalue = event.getX();
    oldYvalue = event.getY();





    return false;

    }else if(event.getAction() == MotionEvent.ACTION_MOVE){
    // 뷰 이동 중

    v.setX(v.getX()+(event.getX())-oldXvalue);

    v.setY(v.getY()+(event.getY())-oldYvalue);

    Log.d("viewTest", "onTouch: ");
    Log.d("viewTest", "onTouch: ");

    }else if(event.getAction() == MotionEvent.ACTION_UP){

    if(v.getX() < 0){
    v.setX(0);
    }else if((v.getX() + v.getWidth()) > parentWidth){
    v.setX(parentWidth - v.getWidth());
    }

    if(v.getY() < 0){
    v.setY(0);
    }else if((v.getY() + v.getHeight()) > parentHeight){
    v.setY(parentHeight - v.getHeight());
    }

    return true;
    }
    return false;
    }






    @Override
    public boolean onLongClick(View v) {

    Toast.makeText(getApplicationContext(), "롱터치"+v.getId()+v.getTag(), Toast.LENGTH_SHORT ).show();

    applyConstraintSet.clone(fit_me_constraintLayout);


    Log.d("imageView_id long_click", "onItemClick:"+v.getId());
    applyConstraintSet.connect(textView2.getId(), ConstraintSet.LEFT, v.getId(), ConstraintSet.RIGHT, 10);

    applyConstraintSet.connect(textView2.getId(), ConstraintSet.TOP, v.getId(), ConstraintSet.TOP, 10);

    applyConstraintSet.connect(textView2.getId(), ConstraintSet.BOTTOM, v.getId(), ConstraintSet.BOTTOM, 10);

    applyConstraintSet.applyTo(fit_me_constraintLayout);


    return true;
    }






    }

    감사합니다.!

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.12.15 22:14 신고

      동적뷰로 하는건 제가 안해본부분이라 도움을 못드릴듯합니다

  2. hw00173@naver.com 2019.12.16 11:36

    넵 ㅠㅠ! 답변 감사합니다.!

+ Recent posts