복합 위젯(compound widget)

유시현·2023년 1월 10일
0

Android

목록 보기
18/34

compound widget : TextView, Image 같은 것을 조합해서 만든 위젯

만드는 과정

1. layout에 만들고자하는 xml 생성

<?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>

2. class 정의(필요하면 인터페이스로 event처리)

여기서 원래 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;
    }
}

3. layout에 추가할때는 풀네임으로

<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();
        }
    }
profile
안드로이드 ,ios 공부하고 있습니다

0개의 댓글