compound widget : TextView, Image 같은 것을 조합해서 만든 위젯
만드는 과정
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_launcher_foreground"
android:id="@+id/image_icon"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="@+id/text_name"/>
</LinearLayout>
여기서 원래 FrameLayout이 아니라 viewGroup을 받는게 맞음
FrameLayout은 기본적인 마진,패팅 속성을 편하게 사용하기 위해서 사용한것
public class ImageTextView extends FrameLayout {
ImageView imageView;
TextView textView;
ImageTextData mData;
OnImageClickListener mImageClickListener;
public ImageTextView(@NonNull Context context) {
super(context);
init();
}
public ImageTextView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ImageTextView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public ImageTextView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
LayoutInflater.from(getContext()).inflate(R.layout.compound_layout,this);
imageView = (ImageView) findViewById(R.id.image_icon);
textView= (TextView) findViewById(R.id.text_name);
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if(mImageClickListener!=null){
mImageClickListener.onImageClick(ImageTextView.this, mData);
}
}
});
}
public void setImageText(ImageTextData data){
mData = data;
imageView.setImageResource(data.imageId);
textView.setText(data.name);
}
public Drawable getImage(){
return imageView.getDrawable();
}
public String getText(){
return textView.getText().toString();
}
public void setOnImageClickListener(OnImageClickListener listener){
mImageClickListener = listener;
}
public interface OnImageClickListener{
public void onImageClick(View v, ImageTextData d);
}
public static class ImageTextData {
public int imageId;
public String name;
}
}
<com.example.compoundwidget.ImageTextView
android:id="@+id/imageTextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
위에서 FrameLayout 상속받아서 형태가
이렇게 되는데 바깥에 있는 FrameLayout은 필요가 없다.(냅두면 메모리만 잡아먹음)
이건 merge로 해결가능하다. merge 태그 밑에 있는 child들을 가져다 붙일 수 있다.
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_launcher_foreground"
android:id="@+id/image_icon"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="@+id/text_name"/>
</merge>
이렇게 하면 LinearLayout child로 merge 밑에 정의된 child들이 붙는다
styleable로 나만의 속성 정의
res/values 밑에
<resources>
<declare-styleable name="ImageTextView">
<attr name="name" format="string"/>
<attr name="image" format="reference"/>
</declare-styleable>
</resources>
layout에서 입력한 정보 가져오기(AttributeSet attrs 여기서 가져올 수 있음)
public ImageTextView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
if(attrs != null){
TypedArray ta = getContext().obtainStyledAttributes(attrs,R.styleable.ImageTextView);
String name = ta.getString(R.styleable.ImageTextView_image);
textView.setText(name);
int resId = ta.getResourceId(R.styleable.ImageTextView_image,R.drawable.ic_launcher_foreground);
imageView.setImageResource(resId);
ta.recycle();
}
}