将<include>标记与?attr/myAttr一起使用

use*_*815 8 android android-layout android-styles android-attributes

我试图在我的视图中包含不同的布局,具体取决于父级Theme.

遵循这个想法:

attrs.xml

<attr name="themeLayout" format="reference" />
Run Code Online (Sandbox Code Playgroud)

styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="themeLayout">@layout/layout_a</item>
</style>

<style name="AppThemeSecond" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="themeLayout">@layout/layout_b</item>
</style>
Run Code Online (Sandbox Code Playgroud)

activity.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <include layout="?attr/themeLayout" />

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

当我运行上面的代码时,我将得到以下异常:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.my.package/com.my.package.MainActivity}: android.view.InflateException: You must specifiy a valid layout reference. The layout ID ?attr/themeLayout is not valid.
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
     Caused by: android.view.InflateException: You must specifiy a valid layout reference. The layout ID ?attr/themeLayout is not valid.
            at android.view.LayoutInflater.parseInclude(LayoutInflater.java:866)
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?是否可以这样做?

注意#1:我设置了ThemeMainActivityandroid:theme="@style/AppTheme"

注意#2:在布局编辑器的设计视图中,一切都按预期工作.如果我切换主题,包括正确更新.
请参阅以下屏幕截图:

预览设计选项卡android studio

Lam*_*rak 4

不幸的是,这是不可能的,但我真的很喜欢这个主意。我已经跟踪了流程LayoutInflater,它需要layout属性,TypedValue.TYPE_REFERENCE这意味着?attr不允许。他们甚至在方法中留下了注释来解释。

public int getAttributeResourceValue(int idx, int defaultValue) {
    int t = nativeGetAttributeDataType(mParseState, idx);
    // Note: don't attempt to convert any other types, because
    // we want to count on aapt doing the conversion for us.
    if (t == TypedValue.TYPE_REFERENCE) {
        return nativeGetAttributeData(mParseState, idx);
    }
    return defaultValue;
}
Run Code Online (Sandbox Code Playgroud)

android.content.res.XmlBlock.java:385

基本上你没有做错什么——预览中的通货膨胀工作方式不同,这导致了混乱。