안드로이드에서 제공하는 뷰에 필요한 기능을 추가하거나, 새로운 뷰를 만들어서 사용해야하는 경우가 생깁니다.
저 같은 경우는 여러 뷰들을 묶어서 하나로 사용하기 위해서 커스텀 뷰를 만들었습니다.
이번 글에서는 하나로 묶어서 쓰는 것을 예제로 커스텀 뷰를 만들어 보겠습니다.
커스텀 뷰 하나를 만듭니다.
[ res > layout > my_custom_layout.xml ]
<?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"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/white_border"
android:padding="10dp"
>
<ImageView
android:id="@+id/ivThumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher_foreground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="제목"
android:textColor="@color/white"
app:layout_constraintBottom_toTopOf="@+id/tvContents"
app:layout_constraintLeft_toRightOf="@+id/ivThumbnail"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/tvContents"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/ivThumbnail"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvTitle"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
요렇게 생겼습니다.
이제 이 커스텀 뷰용 클래스를 하나 만듭니다.
[ MyCustomView.java ]
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
public class MyCustomView extends ConstraintLayout {
View mView;
ImageView ivThumbnail;
TextView tvTitle;
TextView tvContents;
public MyCustomView(@NonNull Context context) {
super(context);
init();
}
public MyCustomView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public MyCustomView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void init(){
LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mView = layoutInflater.inflate(R.layout.my_custom_layout, this, false);
addView(mView);
ivThumbnail = this.findViewById(R.id.ivThumbnail);
tvTitle = this.findViewById(R.id.tvTitle);
tvContents = this.findViewById(R.id.tvContents);
}
}
init() 함수에서 LayoutInFlater는 xml 파일을 View 객체로 반환해주는 역할을 합니다.
이제 커스텀뷰를 만들었으니, 제대로 나오나 확인해보겠습니다.
activity_main.xml 에 추가해주면
<?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"
android:background="@color/black"
>
<com.genue.tester.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
아주 잘나오네요!!
조금 더 활용해 보겠습니다.
지금 커스텀 뷰에는 이미지, 제목, 내용 이렇게 세 개의 값이 있습니다. 이걸 코드 상에서 수정할 수 있지만, xml 파일에서 바꿀 수 있도록 해보겠습니다. 이미 존재하는 뷰들에 보면 android: 이렇게 시작하는 속성이 있고, app: 으로 시작하는 속성이 있습니다. 여기서 app:이 바로 지금 추가할려는 것입니다.
필요한 속성들을 만들겠습니다.
[ res > valus > attrs.xml ]
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCustomView">
<attr name="title" format="string|reference"/>
<attr name="content" format="string|reference"/>
<attr name="thumbnail" format="color|reference"/>
</declare-styleable>
</resources>
name 은 다른 커스텀 속성과 구문되게 하시면 됩니다.
format 값 중 reference 는 id 형태도 쓰기 위해서 넣었습니다. @sting/... , @drawable/...
그리고 아까 만든 MyCustomView.java 를 수정하겠습니다.
package com.genue.tester;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
public class MyCustomView extends ConstraintLayout {
View mView;
ImageView ivThumbnail;
TextView tvTitle;
TextView tvContents;
public MyCustomView(@NonNull Context context) {
super(context);
init();
}
public MyCustomView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
getAttrs(attrs);
}
public MyCustomView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
getAttrs(attrs, defStyleAttr);
}
public void init(){
LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mView = layoutInflater.inflate(R.layout.my_custom_layout, this, false);
addView(mView);
ivThumbnail = this.findViewById(R.id.ivThumbnail);
tvTitle = this.findViewById(R.id.tvTitle);
tvContents = this.findViewById(R.id.tvContents);
}
private void getAttrs(AttributeSet attrs){
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyCustomView);
setTypeArray(typedArray);
}
private void getAttrs(AttributeSet attrs, int defStyle){
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);
setTypeArray(typedArray);
}
private void setTypeArray(TypedArray typedArray){
String title = typedArray.getString(R.styleable.MyCustomView_title);
tvTitle.setText(title);
int thumbnail_resID = typedArray.getResourceId(R.styleable.MyCustomView_thumbnail, R.drawable.ic_launcher_foreground);
ivThumbnail.setBackgroundResource(thumbnail_resID);
String content = typedArray.getString(R.styleable.MyCustomView_contents);
tvContents.setText(content);
typedArray.recycle();
}
}
이렇게 하고 activity_main.xml에서 커스텀뷰를 수정해보면
<com.genue.tester.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:title="타이틀"
app:contents="콘텐츠입니다"
app:thumbnail="@drawable/ic_launcher_background"
/>
잘 바뀐 것을 확인할 수 있습니다!
이렇게 간단한 커스텀뷰를 한번 만들어 봤습니다. 다음번에는 이 커스텀뷰를 활용해서 화면 터치 시 원하는 위치에 찍어보도록 하겠습니다.
'안드로이드' 카테고리의 다른 글
[안드로이드] Custom View 커스텀 뷰 (3) - 애니메이션 추가 및 뻘 짓 (0) | 2021.07.20 |
---|---|
[안드로이드] Custom View 커스텀 뷰 (2) - 화면 터치 시 생성 (0) | 2021.07.16 |
[안드로이드] 네비게이션바 백키 기능 변경 (0) | 2021.07.08 |
[안드로이드] ExoPlayer(2) - 유튜브 영상 재생시키기 (0) | 2021.07.07 |
[안드로이드] ExoPlayer (1) - 이게 뭐야 & 설정하기 & 시작하기 (0) | 2021.07.02 |