Java 如何在切换主题时考虑变化?
我正在开发一款android应用程序,它需要根据服务器提供的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有变化 人名 电
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 }
}
}