切换主题时如何考虑变化?

Inz*_* IT 5 java android themes dynamic

我正在开发一个Android应用程序,它需要根据themeCode服务器的给定切换主题.我正在使用sharePref保存主题代码并应用它setTheme(R.style.themeName);.它的工作正常,直到基本主题属性如

colorPrimary
colorPrimaryDark
colorAccent
windowActionBar
windowNoTitle
Run Code Online (Sandbox Code Playgroud)

为此我创造了不同的风格styles.xml.但我有一个限制,有些领域说EditText有变化为EditText

  • 人名
  • 电子邮件
  • 电话
  • 密码等

并且同样TextView具有TextView的变体

  • 标题
  • 单线
  • Mutiline
  • 链接等

在多主题要求之前,我为所有人创建了单独的主题

  • Apptheme.Edittext.email
  • Apptheme.Edittext.Password
  • Apptheme.Edittext.PersonName等正在申请xml中的特定视图

     style="@style/AppTheme.EditText.PersonName"  
    
    Run Code Online (Sandbox Code Playgroud)

现在我查看了许多教程/帖子,但没有找到属性变体的解决方案.请帮助应用这些变化,我将为此感恩.

问候:Inzimam Tariq

lel*_*man 0

您可以做的是为您的视图类型创建自定义属性(例如TextView.PersonTextView.Date...),在您的 xml 中您可以引用这些属性,然后在不同的主题中定义这些属性。例如,您的 style.xml 可以是

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar" >
        <item name="TextView.Date">@style/DateTextViewDefault</item>
    </style>

    <style name="DateTextViewDefault">
        <item name="android:textColor">#ff333333</item>
        <item name="android:fontFamily">monospace</item>
    </style>

    <!-- Theme A -->
    <style name="AppTheme.A">
        <item name="colorPrimary">#3F51B5</item>
        <item name="colorPrimaryDark">#303F9F</item>
        <item name="colorAccent">#FF4081</item>
        <item name="TextView.Person">@style/PersonTextViewA</item>
    </style>

    <style name="PersonTextViewA">
        <item name="android:textSize">16sp</item>
        <item name="android:fontFamily">serif</item>
        <item name="android:textColor">#ff999999</item>
    </style>

    <!-- Theme B -->
    <style name="AppTheme.B">
        <item name="colorPrimary">#888888</item>
        <item name="colorPrimaryDark">#555555</item>
        <item name="colorAccent">#000000</item>
        <item name="TextView.Person">@style/PersonTextViewB</item>
        <item name="TextView.Date">@style/DateTextViewB</item>
    </style>

    <style name="PersonTextViewB">
        <item name="android:textSize">20sp</item>
        <item name="android:fontFamily">monospace</item>
        <item name="android:textColor">#ff55aa</item>
    </style>

    <style name="DateTextViewB">
        <item name="android:textColor">#ff0000BB</item>
        <item name="android:fontFamily">sans-serif</item>
    </style>

    <attr name="TextView.Person" format="reference" />
    <attr name="TextView.Date" format="reference" />

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

然后你的activity xml布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        style="?attr/TextView.Person"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="John Doe" />

    <TextView
        style="?attr/TextView.Date"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="31/12/1999" />

    <Button
        android:id="@+id/buttonA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="THEME A" />

    <Button
        android:id="@+id/buttonB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="THEME B" />

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

请注意,的样式TextView

style="?attr/TextView.Person"
Run Code Online (Sandbox Code Playgroud)

style="?attr/TextView.Date"
Run Code Online (Sandbox Code Playgroud)

AppTheme.AAppTheme.B这些属性有 2 种不同的分辨率

在此示例中,属性是视图的完整样式,但您可以轻松地为每种视图类型 ( TextView.person) 使用一种样式,然后为该样式的单个项目定义通用属性,例如

<attr name="TextView.Person.TextColor" format="color" />
Run Code Online (Sandbox Code Playgroud)

并且只更改主题中的单个属性。

然后,Activity您只需在onCreatewith中设置主题setTheme(int),在本例中该值可以是R.style.AppTheme_AR.style.AppTheme_B

使用此方法,您可以添加任意数量的样式,而无需更改布局。TextView.Date此外,您始终可以在基本主题中定义一些默认样式,然后仅在某些自定义主题中覆盖该值,而其他主题则使用上面示例中的默认样式。

Activity如果您想快速尝试一下,这是我用来测试style.xmlactivity_main.xml上面的代码

class MainActivity : AppCompatActivity() {

    private val prefs by lazy { getSharedPreferences("SharedPrefs", Context.MODE_PRIVATE) }

    private var customTheme: Int
        get() = prefs.getInt("theme", R.style.AppTheme_A)
        set(value) = prefs.edit()
                .putInt("theme", value)
                .apply()
                .also { recreate() }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setTheme(customTheme)
        setContentView(R.layout.activity_main)

        buttonA.setOnClickListener { customTheme = R.style.AppTheme_A }
        buttonB.setOnClickListener { customTheme = R.style.AppTheme_B }
    }
}
Run Code Online (Sandbox Code Playgroud)