基于 xml 布局(具有预定义属性)创建的自定义视图(不是 ViewGroup)

Custom view (not ViewGroup) created based on xml layout (with predefined attributes)

我想基于 xml 文件实现带有一些预定义属性的自定义 ImageView。为此,我准备了一个包含在 merge 标签中的布局:

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <ImageView
        android:id="@+id/my_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="center"
        android:src="@drawable/icon" />
</merge>

并扩展ImageView class:

public class CustomImageView extends LinearLayout{

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

    public ImageFormField(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ImageFormField(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public ImageFormField(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        View.inflate(getContext(), R.layout.custom_image_view, this);
    }
}

它目前有效,但实际上我不需要 LinearLayout,因为我可以直接从 ImageView 扩展。通过扩展 ImageView 我希望有可能覆盖默认布局中的 src 参数。

所以我删除了 merge 标签,使布局中只有 ImageView 并尝试了这个:

public class CustomImageView extends AppCompatImageView{

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

    public ImageFormField(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ImageFormField(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        View.inflate(getContext(), R.layout.custom_image_view, null); //can't pass root here
    }
}

...但是图片根本显示不出来。我希望能够以这种方式使用我的视图:

<com.my.package.CustomImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

可以覆盖 src 属性。有没有办法通过膨胀布局来做到这一点,还是我必须深入研究属性(包括自定义属性)?

更新 通过“覆盖 src 属性,我的意思是默认情况下图像的来源来自其 xml 文件,但用户可以通过这种方式使用它来在此自定义视图中传递另一个值:

<com.my.package.CustomImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/another_icon" />

要提供 "default" 图像但也允许用户通过指定 android:src 属性覆盖默认值,您可以这样做:

package com.example.Whosebug;

import android.content.Context;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;

public class CustomImageView extends AppCompatImageView {

    public CustomImageView(Context context, AttributeSet attrs) {
        super(context, attrs);

        if (getDrawable() == null) {
            setImageResource(R.drawable.default_image);
        }
    }
}

那么你可以这样使用它:

<!-- will display `default_image` -->
<com.example.Whosebug.CustomImageView
    android:layout_width="200dp"
    android:layout_height="200dp"/>

或者:

<!-- will display `other_image` -->
<com.example.Whosebug.CustomImageView
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:src="@drawable/other_image"/>

无需在自定义图像视图中膨胀任何内容,也无需创建自定义属性(尽管您当然可以创建自定义属性并根据需要使用它们)。

您可以更新 Java 代码以应用其他 "default" 样式。