2015-09-14 75 views
0

我已尝试使用默认样式主题自定义(和派生)视图。 我的解决方案基于answer,但仅适用于api> = 21,并且会在所有早期版本中崩溃。 我正在使用AppCompat appcompat-v7和新的AppCompatActivity基类。主题/风格自定义查看

我的自定义视图:

public class TintableImageButton extends ImageButton { 

    private ColorStateList tint; 

    public TintableImageButton(Context context) { 
     this(context, null); 
    } 

    public TintableImageButton(Context context, AttributeSet attrs) { 
     this(context, attrs, R.attr.tintedImageButtonStyle); 
    } 

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

    @TargetApi(Build.VERSION_CODES.LOLLIPOP) 
    public TintableImageButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
     super(context, attrs, defStyleAttr, defStyleRes); 
     init(context, attrs, defStyleAttr); 
    } 

    private void init(Context context, AttributeSet attrs, int defStyle) { 
     TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TintableImageButton, defStyle, 0); 
     tint = a.getColorStateList(R.styleable.TintableImageButton_tint); 
     a.recycle(); 
    } 
    .... 
} 

不使用tintedImageButtonStyle工作(也发现计算器)的自定义视图。

attr.xml

<resources> 
    <declare-styleable name="TintableImageButton"> 
     <attr name="tint" format="reference|color" /> 
    </declare-styleable> 

    <declare-styleable name="CustomTheme"> 
     <attr name="tintedImageButtonStyle" format="reference"/> 
    </declare-styleable> 
</resources> 

我已经看到一些实例中声明一个声明-设置样式外的主题属性参考。但我不明白区别,特别是在引用的计算器发布中的name =“CustomTheme”的含义。

的themes.xml

<resources> 
    <style name="Base.Theme.ElectroBoxApp" parent="Theme.AppCompat.Light.NoActionBar"> 
     .... 
    </style> 

    <style name="AppBaseTheme" parent="Base.Theme.ElectroBoxApp"> 
     .... 
    </style> 

    <style name="AppTheme" parent="AppBaseTheme"> 
     <item name="tintedImageButtonStyle">@style/TintedImageButton</item> 
    </style> 
</resources> 

styles.xml

<resources> 
    <style name="TintedImageButton" parent="Base.Widget.AppCompat.Button"> 
     <item name="android:minWidth">48dp</item> 
     <item name="android:paddingLeft">4dp</item> 
     <item name="android:paddingRight">4dp</item> 
     <item name="android:clickable">true</item> 
     <item name="android:background">@drawable/btn_default_background</item> 
     <item name="android:scaleType">center</item> 
     <item name="tint">@color/button_tint_csl</item> 
    </style> 
</resources> 

抽拉/ btn_default_background.xml

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:drawable="?attr/selectableItemBackgroundBorderless"/> 
    <item android:top="4dp" android:left="4dp" android:bottom="4dp" android:right="4dp"> 
     <shape android:shape="oval"> 
      <size android:height="30dp" android:width="30dp"/> 
      <solid android:color="?attr/colorAccent"/> 
     </shape> 
    </item> 
</layer-list> 

的AndroidManifest.xml

.... 
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="23"/> 

<application android:allowBackup="true" 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:name=".AppController" 
    android:theme="@style/AppTheme"> 
    .... 
</application> 

样品布局片断

<!-- line 31 is below --> 
<de.NullZero.ManiDroid.presentation.views.TintableImageButton 
     android:id="@+id/btnPlaylist" 
     android:layout_height="wrap_content" 
     android:layout_width="wrap_content" 
     android:src="@drawable/ic_library_music_white_24dp" 
     /> 

在棒棒糖它按预期方式工作,但它会崩溃与上奇巧和下面这种按钮充气的布局。

09-14 12:06:57.800 1939-1962/de.NullZero.ManiDroid E/AndroidRuntime﹕ FATAL EXCEPTION: main 
    Process: de.NullZero.ManiDroid, PID: 1939 
    java.lang.RuntimeException: Unable to start activity ComponentInfo{de.NullZero.ManiDroid/de.NullZero.ManiDroid.presentation.ManiDroidAppActivity}: android.view.InflateException: Binary XML file line #31: Error inflating class de.NullZero.ManiDroid.presentation.views.TintableImageButton 
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195) 
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245) 
      at android.app.ActivityThread.access$800(ActivityThread.java:135) 
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) 
      at android.os.Handler.dispatchMessage(Handler.java:102) 
      at android.os.Looper.loop(Looper.java:136) 
      at android.app.ActivityThread.main(ActivityThread.java:5017) 
      at java.lang.reflect.Method.invokeNative(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:515) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) 
      at dalvik.system.NativeStart.main(Native Method) 
    Caused by: android.view.InflateException: Binary XML file line #31: Error inflating class de.NullZero.ManiDroid.presentation.views.TintableImageButton 
      at android.view.LayoutInflater.createView(LayoutInflater.java:621) 
      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:697) 
      at android.view.LayoutInflater.rInflate(LayoutInflater.java:756) 
      at android.view.LayoutInflater.rInflate(LayoutInflater.java:759) 
      at android.view.LayoutInflater.inflate(LayoutInflater.java:492) 
      at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 
      at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 
      at de.NullZero.ManiDroid.presentation.fragments.MiniPlayerFragment.onCreateView(MiniPlayerFragment.java:70) 
      at android.support.v4.app.Fragment.performCreateView(Fragment.java:1789) 
      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:924) 
      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1116) 
      at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1218) 
      at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2170) 
      at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:300) 
      at android.support.v7.app.AppCompatDelegateImplV7.callActivityOnCreateView(AppCompatDelegateImplV7.java:842) 
      at android.support.v7.app.AppCompatDelegateImplV11.callActivityOnCreateView(AppCompatDelegateImplV11.java:34) 
      at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:830) 
      at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44) 
      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685) 
      at android.view.LayoutInflater.rInflate(LayoutInflater.java:756) 
      at android.view.LayoutInflater.rInflate(LayoutInflater.java:759) 
      at android.view.LayoutInflater.inflate(LayoutInflater.java:492) 
      at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 
      at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 
      at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:249) 
      at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:106) 
      at de.NullZero.lib.navdrawer.AbstractNavDrawerActivity.onCreate(AbstractNavDrawerActivity.java:43) 
      at de.NullZero.ManiDroid.presentation.ManiDroidAppActivity.onCreate(ManiDroidAppActivity.java:75) 
      at android.app.Activity.performCreate(Activity.java:5231) 
      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159) 
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245) 
            at android.app.ActivityThread.access$800(ActivityThread.java:135) 
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) 
            at android.os.Handler.dispatchMessage(Handler.java:102) 
            at android.os.Looper.loop(Looper.java:136) 
            at android.app.ActivityThread.main(ActivityThread.java:5017) 
            at java.lang.reflect.Method.invokeNative(Native Method) 
            at java.lang.reflect.Method.invoke(Method.java:515) 
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) 
            at dalvik.system.NativeStart.main(Native Method) 
    Caused by: java.lang.reflect.InvocationTargetException 
      at java.lang.reflect.Constructor.constructNative(Native Method) 
      at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
      at android.view.LayoutInflater.createView(LayoutInflater.java:595) 
+0

使用下值-21 /的themes.xml一个文件夹中的棒棒糖特定样式属性,这样它不会在预棒棒糖设备上崩溃 – 3xplore

+0

您的绘图/颜色状态列表中是否有引用以根据样式着色? – dtx12

+0

它不是CSL,它是我的默认TintedImageButton风格的背景定义。如果我评论它,它开始在kitkat。但我不知道为什么?我会将我的@ drawable/btn_default_background添加到我的帖子中。 –

回答

0

好吧,我已经找到了一个解决方案,而失去使用默认主题的样式的引用:

我已经改变了我的默认主题风格:

<style name="TintedImageButton" parent="Base.Widget.AppCompat.Button.Borderless"> 
    <item name="android:minWidth">48dp</item> 
    <item name="android:paddingLeft">4dp</item> 
    <item name="android:paddingRight">4dp</item> 
    <item name="android:clickable">true</item> 
    <item name="android:background">?attr/buttonBackground</item> 
    <item name="android:scaleType">center</item> 
    <item name="tint">?attr/buttonTint</item> 
</style> 

我已经将这两个属性添加到我的attr.xml

<declare-styleable name="CustomTheme"> 
    <attr name="tintedImageButtonStyle" format="reference"/> 
    <attr name="buttonTint" format="reference"/> 
    <attr name="buttonBackground" format="reference"/> 
</declare-styleable> 

并在我的themes.xml中选择了属性的值:

<style name="AppTheme" parent="AppBaseTheme"> 
    <!-- All customizations that are NOT specific to a particular API-level can go here. --> 
    <item name="tintedImageButtonStyle">@style/TintedImageButton</item> 
    <item name="buttonTint">@color/button_tint_csl</item> 
    <item name="buttonBackground">?attr/selectableItemBackgroundBorderless</item> 
</style> 

语义相等,但现在它适用于API < 21也没有失去控制;)