我正在使用Android应用程序,该应用程序需要根据服务器提供的themeCode
切换主题。我使用sharePref
保存主题代码并将其应用于setTheme(R.style.themeName);
。它的工作正常,直到
colorPrimary
colorPrimaryDark
colorAccent
windowActionBar
windowNoTitle
为此我在styles.xml
创建了不同的样式。但我有一个限制,有些字段说EditText
的变体为EditText
类似地,TextView
具有TextView
在多主题要求之前,我为所有人创建了单独的主题
Apptheme.Edittext.PersonName等 并且正在应用于xml中的特定视图,如
style="@style/AppTheme.EditText.PersonName"
现在我查看过很多教程/帖子,但没有找到属性变体的解决方案。请帮助应用这些变化,我将为此感恩。
问候: Inzimam Tariq
答案 0 :(得分:1)
在我看来,在运行时更改应用主题,肯定需要重新加载活动;在大多数情况下,这会在某些时候产生问题(如果项目扩展到中等规模,具有用户控制,如切换或切换,如果用户重复切换应用可能很容易崩溃)
我建议使用自定义控件类(Textviews,Buttons..etc);其中,此属性使用sharedPref中的当前主题值进行区分。 这种方法有一个con;它需要手动更改当前屏幕的所有视图和已经在内存中渲染的视图(如果有的话),与传统方法相比,它将更加平滑过渡
这是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" />
我相信,你可以用相同的方式处理控件主题的属性变化。
答案 1 :(得分:0)
您可以为视图类型创建自定义属性(例如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>
然后你的活动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>
请注意TextView
的样式是
style="?attr/TextView.Person"
和
style="?attr/TextView.Date"
AppTheme.A
和AppTheme.B
对这些属性有两种不同的分辨率
在此示例中,属性是视图的整个样式,但您可以轻松地为每种视图类型(TextView.person
)设置一种样式,然后为该样式的单个项目定义通用属性,例如。
<attr name="TextView.Person.TextColor" format="color" />
并且只更改主题中的单个属性。
然后在您的Activity
中,您只需要使用onCreate
在setTheme(int)
中设置主题,在这种情况下,值可以是R.style.AppTheme_A
或R.style.AppTheme_B
使用此方法,您可以根据需要添加任意数量的样式,而无需触摸布局。此外,您始终可以在基本主题中定义一些默认样式,然后仅在某些自定义主题中覆盖该值,而其他人则使用上面示例中TextView.Date
的默认样式。
如果您想快速尝试,请参阅上面Activity
以及style.xml
和activity_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 }
}
}
代码
Oinfo = OStatus.reduce((acc, x) => ({ ...acc, [x]: (acc[x] || 0) + 1 }), {})