package org.aisen.weibo.sina.ui.widget;
import java.lang.reflect.Method;
import org.aisen.weibo.sina.R;
import org.aisen.weibo.sina.support.bean.WallpaperBean;
import org.aisen.weibo.sina.support.utils.AppContext;
import org.aisen.weibo.sina.support.utils.AppSettings;
import org.android.loader.core.BitmapDecoder;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import com.m.common.context.GlobalContext;
import com.m.common.utils.Logger;
import com.m.common.utils.SystemUtility;
import com.m.common.utils.Utils;
/**
* APP背景壁纸
*
* @author Jeff.Wang
*
* @date 2014年10月19日
*/
public class WallpaperViewGroup extends LinearLayout {
public static final String TAG = "Wallpaper";
static {
// Android allows a system property to override the presence of the
// navigation bar.
// Used by the emulator.
// See
// https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
@SuppressWarnings("rawtypes")
Class c = Class.forName("android.os.SystemProperties");
@SuppressWarnings("unchecked")
Method m = c.getDeclaredMethod("get", String.class);
m.setAccessible(true);
sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
} catch (Throwable e) {
sNavBarOverride = null;
}
}
}
private static String sNavBarOverride;
public SystemBarConfig systemBarConfig;
private boolean mStatusBarAvailable;
private boolean mNavBarAvailable;
public static Bitmap wallpaperBitmap;// 壁纸图片
public boolean blur = true;
public WallpaperBean wallpaper;
private Activity activity;
public boolean insertBottom = false;
public WallpaperViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public WallpaperViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public WallpaperViewGroup(Context context) {
super(context);
init(null);
}
private void init(AttributeSet attrs) {
if (activity == null && getContext() instanceof Activity)
activity = (Activity) getContext();
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.Wallpaper);
blur = a.getBoolean(R.styleable.Wallpaper_blur, false);
}
initKitkat();
if (!isKitKat())
mStatusBarAvailable = false;
systemBarConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);
if (!systemBarConfig.hasNavigtionBar()) {
mNavBarAvailable = false;
}
}
@TargetApi(19)
private void initKitkat() {
Window win = activity.getWindow();
// check theme attrs
int[] attrsSys = { android.R.attr.windowTranslucentStatus, android.R.attr.windowTranslucentNavigation };
TypedArray a = activity.obtainStyledAttributes(attrsSys);
try {
mStatusBarAvailable = a.getBoolean(0, false);
mNavBarAvailable = a.getBoolean(1, false);
} finally {
a.recycle();
}
// check window flags
WindowManager.LayoutParams winParams = win.getAttributes();
int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
if ((winParams.flags & bits) != 0) {
mStatusBarAvailable = true;
}
bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
if ((winParams.flags & bits) != 0) {
mNavBarAvailable = true;
}
}
public void setActivity(Activity activity) {
this.activity = activity;
}
public void setBlur(boolean blur) {
this.blur = blur;
}
public void setWallpaper() {
setTranslucent(0, 0);
// 桌面壁纸
if (AppSettings.isLaunchWallpaper()) {
clearTranslucentColor();
setBackground(new ColorDrawable(Color.parseColor("#00000000")));
}
else {
WallpaperBean newWallpaper = AppContext.getWallpaper();
// 删除壁纸
if (newWallpaper == null) {
Logger.d(TAG, "删除壁纸");
wallpaper = null;
wallpaperBitmap = null;
setBackground(new ColorDrawable(getResources().getColor(R.color.bg_content)));
setTranslucentColor();
}
// 设置壁纸
else if (wallpaper == null) {
Logger.d(TAG, "设置壁纸");
wallpaper = newWallpaper;
if (wallpaperBitmap == null) {
wallpaperBitmap = getWallpaperBitmap();
}
setBackground(new BitmapDrawable(getResources(), wallpaperBitmap));
clearTranslucentColor();
}
// 壁纸更新了
else if (!wallpaper.getType().equals(newWallpaper.getType()) || !wallpaper.getPath().equals(newWallpaper.getPath())) {
Logger.d(TAG, "壁纸更新了");
wallpaper = newWallpaper;
// wallpaperBitmap.recycle();
wallpaperBitmap = getWallpaperBitmap();
if (wallpaperBitmap != null)
setBackground(new BitmapDrawable(getResources(), wallpaperBitmap));
}
}
postInvalidate();
}
public void setTranslucent(int topOffset, int bottomOffset) {
// SystemBarTintManager tintManager = SystemBarTintManager.getInstance(activity);
// SystemBarTintManager.SystemBarConfig config = tintManager.getConfig();
int height = systemBarConfig.getPixelInsetTop(true) + Utils.dip2px(topOffset);
View topView = getChildAt(0);
Logger.v(TAG, String.format("child 0, height = %d", height));
topView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height));
// if (height > 0)
// topView.setBackground(new ColorDrawable(Color.parseColor(AppSettings.getThemeColor())));
height = systemBarConfig.getPixelInsetBottom() + Utils.dip2px(bottomOffset);
if (!insertBottom)
height = 0;
View bottomView = getChildAt(2);
bottomView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height));
Logger.v(TAG, String.format("child 2, height = %d", height));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (blur && (wallpaperBitmap != null || AppSettings.isLaunchWallpaper()))
canvas.drawColor(Color.parseColor("#88000000"));
}
private Bitmap getWallpaperBitmap() {
if (wallpaper == null)
return null;
if ("0".equals(wallpaper.getType())) {
WallpaperManager wallpaperManager = WallpaperManager.getInstance(GlobalContext.getInstance());
Bitmap bm = ((BitmapDrawable) wallpaperManager.getDrawable()).getBitmap();
int reqWidth = Math.round(SystemUtility.getScreenHeight() * 1.0f / bm.getHeight() * bm.getWidth());
bm = Bitmap.createBitmap(bm, 0, 0, reqWidth, SystemUtility.getScreenHeight());
return bm;
}
// 默认壁纸
else if ("1".equals(wallpaper.getType())) {
try {
return BitmapFactory.decodeStream(GlobalContext.getInstance().getAssets().open("8_8.jpg"));
} catch (Exception e) {
return BitmapDecoder.decodeSampledBitmapFromFile(wallpaper.getPath(), 800, 1280);
}
}
// 网络默认壁纸
else if ("100".equals(wallpaper.getType())) {
return BitmapDecoder.decodeSampledBitmapFromFile(wallpaper.getPath(), 800, 1280);
}
// 自定义壁纸
else if ("10".equals(wallpaper.getType())) {
return BitmapDecoder.decodeSampledBitmapFromFile(wallpaper.getPath(), 800, 1280);
}
return null;
}
public void setTranslucentColor() {
Drawable colorDrawable = new ColorDrawable(Color.parseColor(AppSettings.getThemeColor()));
ActionBar actionBar = activity.getActionBar();
// 设置ActionBar
if (actionBar != null) {
actionBar.setBackgroundDrawable(colorDrawable);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowTitleEnabled(true);
}
View topView = getChildAt(0);
topView.setBackground(colorDrawable);
View bottomView = getChildAt(2);
bottomView.setBackground(colorDrawable);
}
public void clearTranslucentColor() {
Drawable colorDrawable = new ColorDrawable(Color.parseColor("#00000000"));
ActionBar actionBar = activity.getActionBar();
// 清理ActionBar
if (actionBar != null) {
actionBar.setBackgroundDrawable(colorDrawable);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowTitleEnabled(true);
}
View topView = getChildAt(0);
topView.setBackground(colorDrawable);
View bottomView = getChildAt(2);
bottomView.setBackground(colorDrawable);
}
/**
* Class which describes system bar sizing and other characteristics for the
* current device configuration.
*
*/
public static class SystemBarConfig {
private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";
private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar";
private final boolean mTranslucentStatusBar;
private final boolean mTranslucentNavBar;
private final int mStatusBarHeight;
private final int mActionBarHeight;
private final boolean mHasNavigationBar;
private final int mNavigationBarHeight;
private final int mNavigationBarWidth;
private final boolean mInPortrait;
private final float mSmallestWidthDp;
private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) {
Resources res = activity.getResources();
mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
mSmallestWidthDp = getSmallestWidthDp(activity);
mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);
mActionBarHeight = getActionBarHeight(activity);
mNavigationBarHeight = getNavigationBarHeight(activity);
mNavigationBarWidth = getNavigationBarWidth(activity);
mHasNavigationBar = (mNavigationBarHeight > 0);
mTranslucentStatusBar = translucentStatusBar;
mTranslucentNavBar = traslucentNavBar;
}
@TargetApi(14)
private int getActionBarHeight(Context context) {
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TypedValue tv = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
}
return result;
}
@TargetApi(14)
private int getNavigationBarHeight(Context context) {
Resources res = context.getResources();
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (hasNavBar(context)) {
String key;
if (mInPortrait) {
key = NAV_BAR_HEIGHT_RES_NAME;
} else {
key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
}
return getInternalDimensionSize(res, key);
}
}
return result;
}
@TargetApi(14)
private int getNavigationBarWidth(Context context) {
Resources res = context.getResources();
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (hasNavBar(context)) {
return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);
}
}
return result;
}
@TargetApi(14)
private boolean hasNavBar(Context context) {
Resources res = context.getResources();
int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android");
if (resourceId != 0) {
boolean hasNav = res.getBoolean(resourceId);
// check override flag (see static block)
if ("1".equals(sNavBarOverride)) {
hasNav = false;
} else if ("0".equals(sNavBarOverride)) {
hasNav = true;
}
return hasNav;
} else { // fallback
return !ViewConfiguration.get(context).hasPermanentMenuKey();
}
}
private int getInternalDimensionSize(Resources res, String key) {
int result = 0;
int resourceId = res.getIdentifier(key, "dimen", "android");
if (resourceId > 0) {
result = res.getDimensionPixelSize(resourceId);
}
return result;
}
@SuppressLint("NewApi")
private float getSmallestWidthDp(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
} else {
// TODO this is not correct, but we don't really care pre-kitkat
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
}
float widthDp = metrics.widthPixels / metrics.density;
float heightDp = metrics.heightPixels / metrics.density;
return Math.min(widthDp, heightDp);
}
/**
* Should a navigation bar appear at the bottom of the screen in the
* current device configuration? A navigation bar may appear on the
* right side of the screen in certain configurations.
*
* @return True if navigation should appear at the bottom of the screen,
* False otherwise.
*/
public boolean isNavigationAtBottom() {
return (mSmallestWidthDp >= 600 || mInPortrait);
}
/**
* Get the height of the system status bar.
*
* @return The height of the status bar (in pixels).
*/
public int getStatusBarHeight() {
return mStatusBarHeight;
}
/**
* Get the height of the action bar.
*
* @return The height of the action bar (in pixels).
*/
public int getActionBarHeight() {
return mActionBarHeight;
}
/**
* Does this device have a system navigation bar?
*
* @return True if this device uses soft key navigation, False
* otherwise.
*/
public boolean hasNavigtionBar() {
return mHasNavigationBar;
}
/**
* Get the height of the system navigation bar.
*
* @return The height of the navigation bar (in pixels). If the device
* does not have soft navigation keys, this will always return
* 0.
*/
public int getNavigationBarHeight() {
return mNavigationBarHeight;
}
/**
* Get the width of the system navigation bar when it is placed
* vertically on the screen.
*
* @return The width of the navigation bar (in pixels). If the device
* does not have soft navigation keys, this will always return
* 0.
*/
public int getNavigationBarWidth() {
return mNavigationBarWidth;
}
/**
* Get the layout inset for any system UI that appears at the top of the
* screen.
*
* @param withActionBar
* True to include the height of the action bar, False
* otherwise.
* @return The layout inset (in pixels).
*/
public int getPixelInsetTop(boolean withActionBar) {
return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0);
}
/**
* Get the layout inset for any system UI that appears at the bottom of
* the screen.
*
* @return The layout inset (in pixels).
*/
public int getPixelInsetBottom() {
if (mTranslucentNavBar && isNavigationAtBottom()) {
return mNavigationBarHeight;
} else {
return 0;
}
}
/**
* Get the layout inset for any system UI that appears at the right of
* the screen.
*
* @return The layout inset (in pixels).
*/
public int getPixelInsetRight() {
if (mTranslucentNavBar && !isNavigationAtBottom()) {
return mNavigationBarWidth;
} else {
return 0;
}
}
}
public static boolean isKitKat() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
}
}