在多主题应用中更改单个视图样式的最佳方法

时间:2013-10-01 00:48:12

标签: android android-theme

我的ListView BaseAdapter inflated可以有许多不同的views TextView。我正在实现用户可以在应用程序中选择的树主题。一切都很棒,直到我需要根据用户选择的主题更改ListView中行@Override public View getView(int position, View convertView, ViewGroup parent) { int type = getItemViewType(position); ViewHolder viewHolder = null; if (convertView == null) { switch (type) { case TYPE_ACTIVE: // inflate active accounts if (theme == SettingsManager.InterfaceTheme.light) convertView = inflator.inflate(R.layout.a_login_roaster_light, null); else if (theme == SettingsManager.InterfaceTheme.dark) convertView = inflator.inflate(R.layout.a_login_roaster_dark, null); else convertView = inflator.inflate(R.layout.a_login_roaster_def, null); viewHolder = new ViewHolder(); viewHolder.text1 = (TextView) convertView.findViewById(R.id.txt_row1); viewHolder.text2 = (TextView) convertView.findViewById(R.id.txt_row2); 的外观。

我有一个解决方案,我正在进行这样的测试:

<?xml version="1.0" encoding="utf-8"?>
<!-- File created by the Android Action Bar Style Generator

     Copyright (C) 2011 The Android Open Source Project
     Copyright (C) 2012 readyState Software Ltd

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<resources>

    <style name="Theme.theapp_light" parent="@style/Theme.AppCompat.Light">
        <item name="actionBarItemBackground">@drawable/selectable_background_theapp_light</item>
        <item name="popupMenuStyle">@style/PopupMenu.theapp_light</item>
        <item name="dropDownListViewStyle">@style/DropDownListView.theapp_light</item>
        <item name="actionBarTabStyle">@style/ActionBarTabStyle.theapp_light</item>
        <item name="actionDropDownStyle">@style/DropDownNav.theapp_light</item>
        <item name="actionBarStyle">@style/ActionBar.Solid.theapp_light</item>
        <item name="actionModeBackground">@drawable/cab_background_top_theapp_light</item>
        <item name="actionModeSplitBackground">@drawable/cab_background_bottom_theapp_light</item>
        <item name="actionModeCloseButtonStyle">@style/ActionButton.CloseMode.theapp_light</item>


    </style>

    <style name="ActionBar.Solid.theapp_light" parent="@style/Widget.AppCompat.Light.ActionBar.Solid">
        <item name="background">@drawable/ab_solid_theapp_light</item>
        <item name="backgroundStacked">@drawable/ab_stacked_solid_theapp_light</item>
        <item name="backgroundSplit">@drawable/ab_bottom_solid_theapp_light</item>
        <item name="progressBarStyle">@style/ProgressBar.theapp_light</item>
    </style>

    <style name="ActionBar.Transparent.theapp_light" parent="@style/Widget.AppCompat.Light.ActionBar">
        <item name="background">@drawable/ab_transparent_theapp_light</item>
        <item name="progressBarStyle">@style/ProgressBar.theapp_light</item>
    </style>

    <style name="PopupMenu.theapp_light" parent="@style/Widget.AppCompat.Light.PopupMenu">  
        <item name="android:popupBackground">@drawable/menu_dropdown_panel_theapp_light</item>  
    </style>

    <style name="DropDownListView.theapp_light" parent="@style/Widget.AppCompat.Light.ListView.DropDown">
        <item name="android:listSelector">@drawable/selectable_background_theapp_light</item>
    </style>

    <style name="ActionBarTabStyle.theapp_light" parent="@style/Widget.AppCompat.Light.ActionBar.TabView">
        <item name="android:background">@drawable/tab_indicator_ab_theapp_light</item>
    </style>

    <style name="DropDownNav.theapp_light" parent="@style/Widget.AppCompat.Light.Spinner.DropDown.ActionBar">
        <item name="android:background">@drawable/spinner_background_ab_theapp_light</item>
        <item name="android:popupBackground">@drawable/menu_dropdown_panel_theapp_light</item>
        <item name="android:dropDownSelector">@drawable/selectable_background_theapp_light</item>
    </style>

    <style name="ProgressBar.theapp_light" parent="@style/Widget.AppCompat.ProgressBar.Horizontal">
        <item name="android:progressDrawable">@drawable/progress_horizontal_theapp_light</item>
    </style>

    <style name="ActionButton.CloseMode.theapp_light" parent="@style/Widget.AppCompat.Light.ActionButton.CloseMode">
        <item name="android:background">@drawable/btn_cab_done_theapp_light</item>
    </style>

    <!-- this style is only referenced in a Light.DarkActionBar based theme -->
    <style name="Theme.theapp_light.Widget" parent="@style/Theme.AppCompat">
        <item name="popupMenuStyle">@style/PopupMenu.theapp_light</item>
        <item name="dropDownListViewStyle">@style/DropDownListView.theapp_light</item>
    </style>

</resources>

如你所见,我通过膨胀ny行布局来改变外观。这是有效的,但有更好的方法,因为布局是相同的只有颜色或字体大小必须改变?我正在使用android-support-v7-appcompat.jar并将我的Application Manifest中的Theme.AppCompat.Light主题作为默认主题。我用这个有意思的工具Android Action Bar Style Generator

制作了一些主题

这是使用Android Action Bar Style Generator创建的样式,我发布了一种树样式,因为它们是相同的。这是位于res \ values

中的“轻量级”版本文件
<resources>
    <color name="pressed_theapp_light">#CCFC4C5D</color>
</resources>

这是位于res \ values

中的颜色资源样式
{{1}}

1 个答案:

答案 0 :(得分:1)

编辑:我更新了以下所有内容,以包含我为在列表项上设置自动样式而定义的样式multiListItem

以下是我在我的应用上使用的方式让用户在主题之间切换:

首先我在文件styles.xml中准备不同的主题,这是一个简单的例子,我修改了系统上的默认基本颜色:

<!-- *** DEFAULT THEME *** -->
    <style name="AppTheme" parent="@android:style/Theme.Holo.Light">
        <item name="android:textColorPrimary">?mainColor</item>
        <item name="android:textColorSecondary">?darkColor</item>
        <item name="android:textColorTertiary">?lightColor</item>
    </style>

    <!-- *** ORANGE THEME *** -->
    <style name="AppThemeOrange" parent="@style/AppTheme">
        <item name="mainColor">@color/orange_main</item>
        <item name="lightColor">@color/orange_light</item>
        <item name="darkColor">@color/orange_dark</item>

        <item name="multiListItem">@style/OrangeListViewItemStyle</item>
    </style>

    <!-- *** PURPLE THEME *** -->
    <style name="AppThemePurple" parent="@style/AppTheme">
        <item name="mainColor">@color/purple_main</item>
        <item name="lightColor">@color/purple_light</item>
        <item name="darkColor">@color/purple_dark</item>

        <item name="multiListItem">@style/PurpleListViewItemStyle</item>
    </style>

我还添加了2个主题所需的2种风格:

<style name="OrangeListViewItemStyle">
        <item name="android:textColor">@color/OrangeMain</item>
        <item name="android:textSize">18sp</item>
    </style>

<style name="PurpleListViewItemStyle">
        <item name="android:textColor">@color/PurpleMain</item>
        <item name="android:textSize">20sp</item>
    </style>

然后在列表行项目上调用样式multiListItem,对于这种情况,我在此布局中使用它(为列表中的每一行充气布局):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/filter_list_child_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:attr/activatedBackgroundIndicator"
    android:orientation="horizontal" >

    <CheckBox
        android:id="@+id/filter_list_child_checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:longClickable="false" />

    <TextView
        android:id="@+id/filter_list_child_textview"
        style="?multiListItem"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

</LinearLayout>

所以我有一个默认主题,实际上是从特定的橙色和紫色主题加载引用。 为此,我在文件values\attrs.xml中添加了引用:

<?xml version="1.0" encoding="utf-8"?>
  <resources>
       <attr name="mainColor" format="reference"/>
       <attr name="lightColor" format="reference"/>
       <attr name="darkColor" format="reference"/>

       <attr name="multiListItem" format="reference" />
  </resources>

我还在文件夹selectors中的样式中创建了所有color调用,例如orange_dark.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_enabled="false" android:color="@color/TextGray"/>
    <item android:state_pressed="true" android:color="@color/OrangeLightBackground"/>
    <item android:color="@color/OrangeDark"/>
</selector>

准备好所有这些后,我使用共享首选项加载正确的主题。该主题仅通过填充此列表的列表首选项作为常规设置提供:

<string-array name="themes_strings">
        <item>Purple</item>
        <item>Orange</item>
    </string-array>
    <string-array name="themes_values">
        <item>purple</item>
        <item>orange</item>
    </string-array>

然后,为了检索在设置中选择的主题,我只使用这个简单的函数:

public int getThemeID() {

        String themeSelected = _sharedPrefs.getString(PREF_KEY_THEME, DEFAULT_THEME);
        if(themeSelected.equalsIgnoreCase("orange")){
            return THEME_ORANGE_ID;
        }
        else if(themeSelected.equalsIgnoreCase("purple")){
            return THEME_PURPLE_ID;
        }
        else{
            return THEME_PURPLE_ID;
        }
    }

常量直接使用主题参考定义:

public static final int THEME_ORANGE_ID = R.style.AppThemeOrange;
public static final int THEME_PURPLE_ID = R.style.AppThemePurple;

然后选择的主题应用于使用此行的活动:

setTheme(mPrefs.getThemeID());

mPrefs只是一个帮助类,收集所有共享偏好的getter和setter。

希望它会给你一些想法!