简体   繁体   中英

Create custom layout in XML to initialize in code or in another layout xml

I have encountered an issue i am trying to resolve (or understand better the way it should be done) in creation of custom Layout in Android.

I want to create a custom RelativeLayout class for my use, which is defined in a layout XML file.

my_relative_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<com.mypackage.MyRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:scaleType="fitStart"
        android:src="@drawable/my_drawable"/>
    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/title_gray"
        android:layout_below="@id/image_view"
        android:gravity="center"
        android:text="@string/placeholder" />
</com.mypackage.MyRelativeLayout>

Usage

  public class MyRelativeLayout extends RelativeLayout {
        private AttributeSet attrs;
        private ImageView imageView;
        private TextView textView;

        public MyRelativeLayout(Context context) {
            super(context);
        }

        public MyRelativeLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.attrs = attrs;
        }

        public MyRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            this.attrs = attrs;
        }

        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            if (attrs != null) {
                TypedArray a = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.MyRelativeLayout, 0, 0);
                drawableResource = a.getResourceId(R.styleable.MyRelativeLayout.image_view, 0);
                a.recycle();
            }
            imageView = (ImageView) findViewById(R.id.image_view);
            textView = (TextView) findViewById(R.id.text_view);

            if (drawableResource != 0 && imageView != null) {
                imageView.setImageResource(drawableResource);
            }
        }
    }

My issue is that i want to initialise this layout both in another XML and in code. But as I wrote my class and XML, i can only use it in code by doing:

myLayout = (MyRelativeLayout) LayoutInflater.from(this.getActivity()).inflate(R.layout.my_relative_layout, container, false);

When writing the following in another XML causes the onFinishInflate to fail on getViewById (returns null) and the childrenCount is 0

<com.mypackage.MyRelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_below="@id/another_layout"
    app:image_view="@drawable/my_image" />

and doing the following, won't let me configure the custom image_view attribute.

<include layout="@layout/my_relative_layout"/>

To fix that, i can change the custom layout XML root element to be of type RelativeLayout and add the following to the beginning of onFinishInflate method:

LayoutInflater.from(getContext()).inflate(R.layout.my_relative_layout, this, true);

But the XML won't reference my class.
My questions are,
1. Am i missing something in the definition of the custom layout?
2. What is the correct definition for custom layout?

Thank you in advance!

First you should use the styled attributes in the contractor as shown in this example.

How can you expect from MyRelativeLayout that defined as fallow:

<com.mypackage.MyRelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_below="@id/another_layout"
    app:image_view="@drawable/my_image" />

To be aware of views that are defined in my_relative_layout.xml ?

To make it work you should create a costume layout and add it to com.mypackage.MyRelativeLayout manually.

Some thing like that:

costume_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:scaleType="fitStart"
        android:src="@drawable/my_drawable"/>
    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/title_gray"
        android:layout_below="@id/image_view"
        android:gravity="center"
        android:text="@string/placeholder" />
</RelativeLayout>

Your costume view

public class MyRelativeLayout extends RelativeLayout {
        private AttributeSet attrs;
        private ImageView imageView;
        private TextView textView;

        public MyRelativeLayout(Context context) {
            super(context);
            init();
        }

        public MyRelativeLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }

        public MyRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }

        private void init(Context context){
            LayoutInflater.from(context).inflate(R.layout.costume_layout, this);
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM