Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/194.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在切换主题时考虑变化?_Java_Android_Dynamic_Themes - Fatal编程技术网

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

Java 如何在切换主题时考虑变化?,java,android,dynamic,themes,Java,Android,Dynamic,Themes,我正在开发一款android应用程序,它需要根据服务器提供的themeCode切换主题。我正在使用sharePref保存主题代码,并将其与setTheme(R.style.themeName)一起应用。在基本主题属性如 colorPrimary colorPrimaryDark colorAccent windowActionBar windowNoTitle 为此,我在styles.xml中创建了不同的样式。但是我有一个限制,一些字段说,EditText作为EditText有变化 人名 电

我正在开发一款android应用程序,它需要根据服务器提供的
themeCode
切换主题。我正在使用
sharePref
保存主题代码,并将其与
setTheme(R.style.themeName)一起应用。在基本主题属性如

colorPrimary
colorPrimaryDark
colorAccent
windowActionBar
windowNoTitle
为此,我在
styles.xml
中创建了不同的样式。但是我有一个限制,一些字段说,
EditText
作为EditText有变化

  • 人名
  • 电子邮件
  • 电话
  • 密码等
同样地,
TextView
也与TextView不同

  • 标题
  • 单线
  • 多线
  • 链接等
在多主题需求之前,我已经为所有as创建了单独的主题

  • Apptheme.Edittext.email
  • Apptheme.Edittext.Password
  • Apptheme.Edittext.PersonName等。 并应用于xml中的特定视图,如

     style="@style/AppTheme.EditText.PersonName"  
    
现在我看了很多教程/帖子,但没有找到解决属性变化的方法。请帮助应用这些变化,我将对此表示感谢

关于:
Inzimam Tariq

在我看来,在运行时更改应用程序主题肯定需要重新加载活动;在大多数情况下,这会在某一点上产生问题(如果项目扩展到中等规模,有一个用户控件类似于切换或开关,并且如果用户反复点击开关,应用程序可能很容易崩溃)


我建议使用自定义控件类(文本视图、按钮等);其中,该属性与sharedPref中的当前主题值不同。 这种方法有缺点;它需要手动更改当前屏幕的所有视图以及内存中已渲染的视图(如果有的话),与传统方法相比,它将是更平滑的过渡

编辑:CustomTextView的示例## 这是customtextview类的一个示例

public class CustomTextView extends android.support.v7.widget.AppCompatTextView {
private static final String TAG = "TextView";
private Typeface tf = null;
private SharedPreferenceUtils preferenceUtils = SharedPreferenceUtils.getInstance();

/**
 * @param context:This is an abstract class whose implementation is provided by Android Operating System.
 * @param attrs:A      collection of attributes, as found associated with a tag in an XML document.
 * @param defStyle:
 */
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    if (preferenceUtils.getBooleanValue(PrefsKeyValue.bTheme)) {
        this.setTextColor(ResourceUtils.getColor(R.color.lightThemeTextColor));
    } else {
        this.setTextColor(ResourceUtils.getColor(R.color.colorWhite));
    }

    try {
        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.CustomEditText, defStyle, 0);

        String str = a.getString(R.styleable.CustomTextView_FontEnum);
        int original = a.getInt(R.styleable.CustomEditText_FontEnum, 0);
        CustomEnum.CustomFontType customEnumValue = CustomEnum.CustomFontType.fromId(a.getInt(R.styleable.CustomEditText_FontEnum, 0));
        a.recycle();
        switch (customEnumValue) {
            case BOLD:
                setTypeface(HelveticaNeueBold.getInstance(context).getTypeFace());
                break;

            case LIGHT:
                setTypeface(HelveticaNeueMedium.getInstance(context).getTypeFace());
                break;

            case REGULAR:
                setTypeface(HelveticaNeue.getInstance(context).getTypeFace());
                break;

            default:
                break;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public CustomTextView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}


public boolean setCustomFont(Context ctx, String asset) {

    try {
        tf = Typeface.createFromAsset(ctx.getAssets(), asset);
    } catch (Exception e) {
        LogUtils.LogE(TAG, "Could not get typeface: " + e.getMessage());
        return false;
    }

    setTypeface(tf);
    return true;
}}
在此,我根据sharedPref的主题值更改了textcolor

 if (preferenceUtils.getBooleanValue(PrefsKeyValue.bTheme)) {
        this.setTextColor(ResourceUtils.getColor(R.color.lightThemeTextColor));
    } else {
        this.setTextColor(ResourceUtils.getColor(R.color.colorWhite));
    }
然后将该类用作xml文件中的textview标记

    <com.mypkg.customview.CustomTextView
    style="@style/signup_textViewStyle"
    android:text="@string/activity_login_password" />


我相信,您可以用相同的方式处理控件的主题属性变化

您可以为视图类型创建自定义属性(例如,
TextView.Person
TextView.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>

AppTheme.A
AppTheme.B
对这些属性有两种不同的分辨率

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

<attr name="TextView.Person.TextColor" format="color" />

在我的应用程序中,用户不会更改主题,它将由服务器上应用程序的所有者设置。因此,在实例化任何视图之前,我都可以设置主题。设置主题不是问题,问题是如何处理变化。您能添加一个简短的示例吗?如何将第二个参数传递给构造函数?我的意思是属性集属性不需要按语法调用构造函数。只需将属性添加到上面的if-else和xml中,并按照findview添加,就可以了。随着属性和样式变化的增加,这将是一个漫长的过程。再短一点就好了,要不然我就试试这条路。无论如何+1&谢谢你的努力。上面的代码在Kotline中吗?这看起来不像Java类是正确的Kotlin@InzimamTariqIT请注意,该解决方案与Kotlin完全无关,这只是一个快速测试
style="?attr/TextView.Person"
style="?attr/TextView.Date"
<attr name="TextView.Person.TextColor" format="color" />
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 }
    }
}