Android 实现切换主题皮肤功能(类似于众多app中的 夜间模式,主题包等)
首先来个最简单的一键切换主题功能,就做个白天和晚上的主题好了。
先看我们的styles文件:
<resources> <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> <!--白天主题-->
<style name="dayTheme" parent="AppTheme">
<item name="android:textColor">#525252</item>
<item name="android:background">#f7f7f7</item>
</style> <!--夜间主题-->
<style name="nightTheme" parent="AppTheme">
<item name="android:textColor">#868a96</item>
<item name="android:background">#1e1e2a </item>
</style> </resources>
好,然后我们来看看主要activity
package com.example.administrator.mainchangethemeapp; import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView tv; @Override
protected void onCreate(Bundle savedInstanceState) {
//sputils是對SharedPreferences的封裝,代碼就不上了,大家理解意思就行了
if(SPUtils.get(this,"theme","dayTheme").equals("dayTheme"))
{
//默認是白天主題
setTheme(R.style.dayTheme);
}else
{
//否则是晚上主題
setTheme(R.style.nightTheme);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); tv=(TextView)this.findViewById(R.id.tv);
tv.setOnClickListener(new View.OnClickListener(){ @Override
public void onClick(View v) {
if(SPUtils.get(MainActivity.this,"theme","dayTheme").equals("dayTheme"))
{
SPUtils.put(MainActivity.this,"theme","nightTheme");
}else
{
SPUtils.put(MainActivity.this, "theme", "dayTheme");
}
recreate();
}
});
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId(); //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} return super.onOptionsItemSelected(item);
}
}
然后来看下效果:
当然了,上面这个demo实际上是有缺陷的。有人会说了 你看人家新浪微博,那么多主题,你要是用这种方法,你这个app得有多大,
能做成微博那样要用什么就去下载什么么?答案是可以的。其实方案也很简单。
这种方案的思路就是,把主题包 额外做成一个apk,注意这个apk 是不会在桌面显示的。你只能在设置里的app列表里找到他。
然后在你的主activity里 取这个apk里的资源 即可。这里我也把这种方案的代码写一遍。注意下载apk 安装apk的代码我就不写了。
我们就假设 我们要切换的主题就是系统自带的主题就行了,我们的主activity 使用的是白天主题。然后我们的子app里面
为了简化代码,我们就不放自定义主题了,就使用android studio 原始的代码,一步步来,
先放上子app里的styles文件,其实这个里面一行代码都没更改,全是ide自己生成的:
<resources> <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> </resources>
然后就是子activity里的 配置文件manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.administrator.sonproject" > <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
</application> </manifest>
注意这里
<category android:name="android.intent.category.LAUNCHER" /> 的这行代码 我是没写的。这样就是保证在这个apk 安装好以后不会在桌面出现。
然后我们来看看主activity代码
package com.example.administrator.mainchangethemeapp; import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView tv; @Override
protected void onCreate(Bundle savedInstanceState) {
//sputils是對SharedPreferences的封裝,代碼就不上了,大家理解意思就行了
if (SPUtils.get(this, "theme", "dayTheme").equals("dayTheme")) {
//默認是白天主題
setTheme(R.style.dayTheme);
} else {
//否则是晚上主題,這裡晚上主題我們就去加載我們晚上主題apk里的資源
int resourceId = getResourceId(getPackageContext(this, "com.example.administrator.sonproject"), "style", "AppTheme");
setTheme(resourceId);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) this.findViewById(R.id.tv);
tv.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
if (SPUtils.get(MainActivity.this, "theme", "dayTheme").equals("dayTheme")) {
SPUtils.put(MainActivity.this, "theme", "nightTheme");
} else {
SPUtils.put(MainActivity.this, "theme", "dayTheme");
}
recreate();
}
});
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId(); //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} return super.onOptionsItemSelected(item);
} /**
* 获取其他apk的context
* @param context
* @param packageName
* @return
*/
public static Context getPackageContext(Context context, String packageName) {
try {
return context.createPackageContext(packageName, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return null;
} //获取指定context的 type里面的 name属性
public static int getResourceId(Context context, String type, String name) {
return context.getResources().getIdentifier(name, type, context.getPackageName());
}
}
你看,到这里 我们就实现了,动态加载主题的方式了。当然了,到这里依旧是不完美的,因为settheme方法大家都知道一定要重启activity才有效啊。这样就不好了。
体验并非最佳。总是给人很突兀的感觉。而且我们都知道重启activity的成本很大。要考虑很多生命周期之类的东西。那我们继续往下看,看看有什么比较好的解决方案能解决这个问题。
首先 我们可以考虑一下这个问题,所谓的切换主题 之类的,无非就是把你那些控件的 背景色啊 字体颜色之类的 改变了一下。对于一个app来说,用户一般只有一个界面 会有切换主题的这个入口,
换句话说,我们的app里面 只有这一个activity 需要实现 不重启activity就切换 控件style的功能,其他activity我们是不需要实现这个功能的,因为再切换过去的时候基本上都会走oncreate。所以
我们只需要考虑这个 有切换主题按钮的 这个activity能实现 不重启activity就换皮肤的功能就可以了。其他activity不需要考虑。so 这样一想 这个功能就简单清晰了很多。
首先我们可以自定义2个属性,我们把他放在attrs 这个xml里面
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 首先自定义属性,这里我们为了简便 只自定义了这2种属性,如果你要自己做的话 看需求可以增加属性-->
<!-- 另外注意我们这里并没有使用declare-styleable 来包裹这里的2个属性 好处就是在xml文件里 不用另外定义前缀了-->
<attr name="custom_background" format="reference|color"/>
<attr name="custom_textcolor" format="reference|color"/>
</resources>
然后我们去定义一下我们的主题:
<resources> <!-- 这里就设置2个最简单的 主题就行了,-->
<!--白天主题-->
<style name="dayTheme" >
<item name="custom_background">#f7f7f7</item>
<item name="custom_textcolor">#525252</item>
</style> <!--晚上主题-->
<style name="nightTheme">
<item name="custom_background">#1e1e2a</item>
<item name="custom_textcolor">#868a96</item>
</style>
</resources>
然后我们来写一下mainactivity的xml布局文件,我们假设这个布局是非常简单的:
<?xml version="1.0" encoding="utf-8"?>
<com.example.administrator.mainchangethemeapp.ThemeRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/custom_background"
android:id="@+id/mainview"
> <com.example.administrator.mainchangethemeapp.ThemeTextView
android:id="@+id/tv"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:text="一鍵切換主題"
android:background="?attr/custom_background"
android:textColor="?attr/custom_textcolor"
/> </com.example.administrator.mainchangethemeapp.ThemeRelativeLayout>
你看这个布局里面 就一个relativelayout和一个textview。 和以前xml唯一的区别就是这里backaground和textcolor使用的值 是我们前面定义好的属性了(但是要注意 这属性是没有值的 赋值的操作放在java代码里实现)。同时这2个控件 也并非是系统控件 而是自定义控件。然后我们看看这个自定义控件是怎么写的。注意我这里就做了2个自定义控件,如果你们的那个切换主题的入口页面里面有其他控件的话,就要学着下面的方法 自己拓展一下了,其实也很简单的。
首先呢,我们来定义一个接口,谁实现了这个接口 就说明这个控件可以不启动activity直接换肤!
package com.example.administrator.mainchangethemeapp; import android.content.res.Resources;
import android.view.View; /**
* Created by Administrator on 2015/11/14.
*/
public interface ThemeUIInterface { public View getView();
public void setTheme(Resources.Theme themeId);
}
然后我们来看看2个自定义控件怎么写:
package com.example.administrator.mainchangethemeapp; import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout; /**
* Created by Administrator on 2015/11/14.
*/
public class ThemeRelativeLayout extends RelativeLayout implements ThemeUIInterface{ private int attr_background = -1; public ThemeRelativeLayout(Context context) {
super(context);
} public ThemeRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.attr_background =ViewAttributeUtil.getBackgroundAttibute(attrs);
} public ThemeRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.attr_background =ViewAttributeUtil.getBackgroundAttibute(attrs); } @Override
public View getView() {
return this;
} @Override
public void setTheme(Resources.Theme themeId) {
if(attr_background!=-1) {
ViewAttributeUtil.applyBackgroundDrawable(this, themeId, attr_background);
}
}
}
package com.example.administrator.mainchangethemeapp; import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView; /**
* Created by Administrator on 2015/11/16.
*/
public class ThemeTextView extends TextView implements ThemeUIInterface{ private int attr_drawable=-1;
private int attr_textColor=-1; public ThemeTextView(Context context) {
super(context);
} public ThemeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
this.attr_drawable = ViewAttributeUtil.getBackgroundAttibute(attrs);
this.attr_textColor = ViewAttributeUtil.getTextColorAttribute(attrs);
} public ThemeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.attr_drawable = ViewAttributeUtil.getBackgroundAttibute(attrs);
this.attr_textColor = ViewAttributeUtil.getTextColorAttribute(attrs);
} @Override
public View getView() {
return this;
} @Override
public void setTheme(Resources.Theme themeId) {
if (attr_drawable != -1) {
ViewAttributeUtil.applyBackgroundDrawable(this, themeId, attr_drawable);
}
if (attr_textColor != -1) {
ViewAttributeUtil.applyTextColor(this, themeId, attr_textColor);
}
}
}
看上去 其实也蛮简单的对吧,无非就相比传统控件,他对外暴露了 setTheme这个方法罢了,而这个setTheme方法 其实就做了一件事,调用系统自己的方法重新set那些属性罢了。
package com.example.administrator.mainchangethemeapp; import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView; public class ViewAttributeUtil { public static int getAttributeValue(AttributeSet attr, int paramInt) {
int value = -1;
int count = attr.getAttributeCount();
for(int i = 0; i <count;i++) {
if(attr.getAttributeNameResource(i) == paramInt) {
String str = attr.getAttributeValue(i);
if(null != str && str.startsWith("?")) {
value = Integer.valueOf(str.substring(1, str.length())).intValue();
return value;
}
}
}
return value;
} public static int getBackgroundAttibute(AttributeSet attr) {
return getAttributeValue(attr , android.R.attr.background);
} public static int getTextColorAttribute(AttributeSet attr) {
return getAttributeValue(attr, android.R.attr.textColor);
} public static void applyBackgroundDrawable(ThemeUIInterface ci, Resources.Theme theme, int paramInt) {
TypedArray ta = theme.obtainStyledAttributes(new int[]{paramInt});
Drawable drawable = ta.getDrawable(0);
if(null != ci) {
(ci.getView()).setBackgroundDrawable(drawable);
}
ta.recycle();
}
public static void applyTextColor(ThemeUIInterface ci, Resources.Theme theme, int paramInt) {
TypedArray ta = theme.obtainStyledAttributes(new int[]{paramInt});
int resourceId = ta.getColor(0,0);
if(null != ci && ci instanceof TextView) {
((TextView)ci.getView()).setTextColor(resourceId);
}
ta.recycle();
} }
好,到这里 脉络就逐渐清晰了,我们就看看主activity里怎么写了:
package com.example.administrator.mainchangethemeapp; import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView; public class MainActivity extends Activity { private TextView tv; private View view; @Override
protected void onCreate(Bundle savedInstanceState) {
//这行代码千万不能漏掉,否则会报错的。因为你在xml里 的那些值 根本就没有实际的值,如果不在这里强制性的setTheme就直接报错了
//在实际使用中 我们当然可以把这个方法 放在baseactivity里面。我们这里默认主题就白天吧
setTheme(R.style.dayTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//这个就是跟布局
view = this.findViewById(R.id.mainview);
tv = (TextView) this.findViewById(R.id.tv);
tv.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) { //这边逻辑没啥好说的 其实可以不需要看啊,就是白天就切换到黑夜 黑夜就切换到白天呗
if (SPUtils.get(MainActivity.this, "theme", "dayTheme").equals("dayTheme")) {
SPUtils.put(MainActivity.this, "theme", "nightTheme");
setTheme(R.style.nightTheme);
} else {
SPUtils.put(MainActivity.this, "theme", "dayTheme");
setTheme(R.style.dayTheme);
}
//这个方法就是实现不重启页面切换主题的
ThemeUiUtil.changeTheme(view, getTheme());
}
});
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId(); //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} return super.onOptionsItemSelected(item);
} }
然后看一下切换主题的方法是怎么做的:
package com.example.administrator.mainchangethemeapp; import android.content.res.Resources;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; /**
* Created by Administrator on 2015/11/14.
*/
public class ThemeUiUtil {
/**
* 切换应用主题
*
* @param rootView
*/
public static void changeTheme(View rootView, Resources.Theme theme) {
//這裡邏輯很簡單 就是递归调用changeTheme-----递归调用setTheme了。
//注意 你们如果是listview也包含在里面的话 listview自定义实现接口的时候要稍微复杂一些,看你们需要不需要也刷新listview里的item了
//这里为了简单 我就不写那么复杂了,就这一个逻辑:先set自己的theme 然后遍历自己的子控件 逐一set
if (rootView instanceof ThemeUIInterface) {
((ThemeUIInterface) rootView).setTheme(theme);
if (rootView instanceof ViewGroup) {
int count = ((ViewGroup) rootView).getChildCount();
for (int i = 0; i < count; i++) {
changeTheme(((ViewGroup) rootView).getChildAt(i), theme);
}
}
}
} }
你看,到这里 我们不重启activity实现换肤的功能就基本实现了,当然要做的完美的话 还需要各位自己扩充一下 其他控件。但是思路都是一样的。
看到这里 有人仍然会说,你这个虽然没有重启activity,但是还是不好看呀,还是显的突兀了,能否做到知乎 android app那样 切换白天黑夜主题的时候 显的很柔顺呢。
答案是可以的,而且解决方案也比较简单。就是给个动画就完事了,在切换前 先保留一下 之前界面的bitmap 然后切换皮肤的的时候 把这个bitmap 显示出来以后 然后改变他的
alpha值 就可以了,当全部动画显示结束以后 把那些不需要的资源全部释放 就ok了!
来看下代码,这里就放出点击事件的代码了,其他地方与前面的代码一致:
{ //我们先取这个根布局的 bitmap缓存 这个实际上跟截屏是差不多的一个东西。
view.setDrawingCacheEnabled(true);
view.buildDrawingCache(true);
final Bitmap localBitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false); //这边逻辑没啥好说的 其实可以不需要看啊,就是白天就切换到黑夜 黑夜就切换到白天呗
if (SPUtils.get(MainActivity.this, "theme", "dayTheme").equals("dayTheme")) {
SPUtils.put(MainActivity.this, "theme", "nightTheme");
setTheme(R.style.nightTheme);
} else {
SPUtils.put(MainActivity.this, "theme", "dayTheme");
setTheme(R.style.dayTheme);
}
//我们new出来的这个蒙版view --mengbanview 就把他放到跟布局view里面 并且让他充满 同时这个view的background就是截屏前我们的那个截图bitmap
final View mengbanView = new View(getApplicationContext());
mengbanView.setBackgroundDrawable(new BitmapDrawable(getResources(), localBitmap));
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
((ViewGroup) view).addView(mengbanView, params);
mengbanView.animate().alpha(0).setDuration(400).setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
//这个方法就是实现不重启页面切换主题的
ThemeUiUtil.changeTheme(view, getTheme());
} @Override
public void onAnimationEnd(Animator animation) {
//动画结束的时候移出这个蒙版view 并释放bitmap
((ViewGroup) view).removeView(mengbanView);
localBitmap.recycle();
} @Override
public void onAnimationCancel(Animator animation) { } @Override
public void onAnimationRepeat(Animator animation) { }
}).start(); }
最后来看下效果是否和知乎一样:
大功告成,看上去自然多了!
Android 实现切换主题皮肤功能(类似于众多app中的 夜间模式,主题包等)的更多相关文章
- jQuery实现无刷新切换主题皮肤功能
主题皮肤切换功能在很多网站和系统中应用,用户可以根据此功能设置自己喜欢的主题颜色风格,增强了用户体验.本文将围绕如何使用jQuery实现点击无刷新切换主题皮肤功能. 查看演示DEMO:https:// ...
- Android应用开发中的夜间模式实现(一)
前言 在应用开发中会经常遇到要求实现夜间模式或者主题切换具体例子如下,我会先讲解第一种方法. 夜间模式 知乎 网易新闻 沪江开心词场 Pocket 主题切换 腾讯QQ 新浪微博 我今天主要是详述第一种 ...
- iOS 主题/皮肤之 SakuraKit
前言 目前市场上很多 App 都有主题变更.皮肤切换的功能.随着项目代码量的不断增长,业务不断完善,功能性代码逐渐趋于模块化,尤其是在多人协作开发同一个项目时,模块解耦尤为重要,同时,公共基础库的功能 ...
- iOS主题/皮肤之SakuraKit
概述 目前市场上很多 App 都有主题变更.皮肤切换的功能.随着项目代码量的不断增长,业务不断完善,功能性代码逐渐趋于模块化,尤其是在多人协作开发同一个项目时,模块解耦尤为重要,同时,公共基础库的功能 ...
- Android 利用an框架快速实现夜间模式的两种套路
作者:Bgwan链接:https://zhuanlan.zhihu.com/p/22520818来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 网上看到过大多实现夜间模 ...
- android夜间模式实现
一.概述 android夜间模式实现分为两大类 重启activity的实现 不重启activity的实现 二.正文 1.重启activity实现夜间模式[在界面文件中的实现部分] 1.1在attrs. ...
- Android白天/夜间模式Day/Night Mode标准原生SDK实现
Android白天/夜间模式Day/Night Mode标准原生SDK实现 章节A:Android实现白天/夜间模式主要控制器在于UiModeManager,UiModeManager是Andr ...
- Android实现夜间模式
如今非常多App都有夜间模式,特别是阅读类的App.夜间模式如今已经是阅读类App的标配了,其实,日间模式与夜间模式就是给App定义并应用两套不同颜色的主题,用户能够自己主动或者手动的开启,今天用An ...
- Android应用切换皮肤功能实现(二)
原文地址http://www.apkbus.com/forum.php?mod=viewthread&tid=149034&highlight=%E7%9A%AE%E8%82%A4 上 ...
随机推荐
- iframe父子兄弟之间调用传值(contentWindow && parent)
iframe的调用包括以下几个方面:(调用包含html dom,js全局变量,js方法) 主页面调用iframe: iframe页面调用主页面: 主页面的包含的iframe之间相互调用: 主要知识点 ...
- IDTHook 深入学习
在之前的一篇文章中介绍了替换IDT向量表中的地址来达到Hook的目的 IDT hook KiTrap03 但是这样很容易就可以被检测了.接下来要学习就是通过patch GDT来达到Hook IDT的目 ...
- appium自动化测试中获取toast消息的解决方法【转】
http://blog.csdn.net/hqzxsc2006/article/details/50036911 待实践.. 解决方法:appium下切换selendroid模式去获取Android的 ...
- WebSocket API简介
WebSocket是html5新增加的一种通信协议,目前流行的浏览器都支持这个协议,例如Chrome,Safari,Firefox,Opera,IE等等,对该协议支持最早的应该是chrome,从chr ...
- 在.NET中使用Newtonsoft.Json转换,读取,写入的方法介绍
全局引用 using Newtonsoft.Json; using Newtonsoft.Json.Converters; //把Json字符串反序列化为对象 目标对象 = JavaScriptCon ...
- lintcode:交错正负数
交错正负数 给出一个含有正整数和负整数的数组,重新排列成一个正负数交错的数组. 注意事项 不需要保持正整数或者负整数原来的顺序. 样例 给出数组[-1, -2, -3, 4, 5, 6],重新排序之后 ...
- 545C. Woodcutters
题目链接 题意: n个树,在x1,x2,...,xn的位置,树的高度依次是h1,h2,...,hn 求的是当把树砍倒时候,不占用相邻树的位置,最大砍树个数 可向左 向右砍,即树向左向右倒,很显然 当树 ...
- 应用内存优化之OnLowMemory&OnTrimMemory
1.应用内存onLowMemory& onTrimMemory优化 onLowMemory& onTrimMemory简介:OnLowMemory是Android提供的API,在系统内 ...
- java cache过期策略两种实现,一个基于list轮询一个基于timer定时
最近项目要引入缓存机制,但是不想引入分布式的缓存框架,所以自己就写了一个轻量级的缓存实现,有两个版本,一个是通过timer实现其超时过期处理,另外一个是通过list轮询. 首先要了解下ja ...
- 【java】String类和StringBuffer类常用操作
String类是字符串常量,是不可更改的常量.而StringBuffer是字符串变量,它的对象是可以扩充和修改的.StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于Stri ...