另外一种设置沉浸式标题栏的方式

今天又看到了另外一种设置沉浸式标题栏的方式,比上次写的那个使用主题,设置主题背景色的要好很多了。尤其是设置主题背景色后,程序从后台到前台ui界面没加载出来会显示出短暂的标题栏的颜色,因此设置主题背景颜色的方式还是有些缺陷。

废话不多说,我介绍的这个方法使用了小米的一个类:SystemBarTintManager

小米官网的地址 http://dev.xiaomi.com/doc/p=4769/index.html

经过测试在其他的手机上一样适用,只是那个设置标题栏字体颜色为黑色不能用而已。

  1 /*

  2  * Copyright (C) 2013 readyState Software Ltd

  3  *

  4  * Licensed under the Apache License, Version 2.0 (the "License");

  5  * you may not use this file except in compliance with the License.

  6  * You may obtain a copy of the License at

  7  *

  8  *      http://www.apache.org/licenses/LICENSE-2.0

  9  *

 10  * Unless required by applicable law or agreed to in writing, software

 11  * distributed under the License is distributed on an "AS IS" BASIS,

 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 13  * See the License for the specific language governing permissions and

 14  * limitations under the License.

 15  */

 16 

 17 package com.readystatesoftware.systembartint;

 18 

 19 import java.lang.reflect.Field;

 20 import java.lang.reflect.Method;

 21 

 22 import android.annotation.SuppressLint;

 23 import android.annotation.TargetApi;

 24 import android.app.Activity;

 25 import android.content.Context;

 26 import android.content.res.Configuration;

 27 import android.content.res.Resources;

 28 import android.content.res.TypedArray;

 29 import android.graphics.drawable.Drawable;

 30 import android.os.Build;

 31 import android.util.DisplayMetrics;

 32 import android.util.TypedValue;

 33 import android.view.Gravity;

 34 import android.view.View;

 35 import android.view.ViewConfiguration;

 36 import android.view.ViewGroup;

 37 import android.view.Window;

 38 import android.view.WindowManager;

 39 import android.widget.FrameLayout.LayoutParams;

 40 

 41 /**

 42  * Class to manage status and navigation bar tint effects when using KitKat

 43  * translucent system UI modes.

 44  *

 45  */

 46 public class SystemBarTintManager {

 47 

 48     /**

 49      * The default system bar tint color value.

 50      */

 51     public static final int DEFAULT_TINT_COLOR = 0x99000000;

 52 

 53     private final SystemBarConfig mConfig;

 54     private boolean mStatusBarAvailable;

 55     private boolean mNavBarAvailable;

 56     private boolean mStatusBarTintEnabled;

 57     private boolean mNavBarTintEnabled;

 58     private View mStatusBarTintView;

 59     private View mNavBarTintView;

 60     private static boolean sIsMiuiV6;

 61 

 62     static {

 63         try {

 64             Class<?> sysClass = Class.forName("android.os.SystemProperties");

 65             Method getStringMethod = sysClass.getDeclaredMethod("get", String.class);

 66             sIsMiuiV6 = "V6".equals((String) getStringMethod.invoke(sysClass, "ro.miui.ui.version.name"));

 67         } catch (Exception e) {

 68             e.printStackTrace();

 69         }

 70     }

 71 

 72     /**

 73      * Constructor. Call this in the host activity onCreate method after its

 74      * content view has been set. You should always create new instances when

 75      * the host activity is recreated.

 76      *

 77      * @param activity The host activity.

 78      */

 79     @TargetApi(19)

 80     public SystemBarTintManager(Activity activity) {

 81 

 82         Window win = activity.getWindow();

 83         ViewGroup decorViewGroup = (ViewGroup) win.getDecorView();

 84 

 85         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

 86             // check theme attrs

 87             int[] attrs = {android.R.attr.windowTranslucentStatus,

 88                     android.R.attr.windowTranslucentNavigation};

 89             TypedArray a = activity.obtainStyledAttributes(attrs);

 90             try {

 91                 mStatusBarAvailable = a.getBoolean(0, false);

 92                 mNavBarAvailable = a.getBoolean(1, false);

 93             } finally {

 94                 a.recycle();

 95             }

 96 

 97             // check window flags

 98             WindowManager.LayoutParams winParams = win.getAttributes();

 99             int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;

100             if ((winParams.flags & bits) != 0) {

101                 mStatusBarAvailable = true;

102             }

103             bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;

104             if ((winParams.flags & bits) != 0) {

105                 mNavBarAvailable = true;

106             }

107         }

108 

109         mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);

110         // device might not have virtual navigation keys

111         if (!mConfig.hasNavigtionBar()) {

112             mNavBarAvailable = false;

113         }

114 

115         if (mStatusBarAvailable) {

116             setupStatusBarView(activity, decorViewGroup);

117         }

118         if (mNavBarAvailable) {

119             setupNavBarView(activity, decorViewGroup);

120         }

121 

122     }

123 

124     /**

125      * Enable tinting of the system status bar.

126      *

127      * If the platform is running Jelly Bean or earlier, or translucent system

128      * UI modes have not been enabled in either the theme or via window flags,

129      * then this method does nothing.

130      *

131      * @param enabled True to enable tinting, false to disable it (default).

132      */

133     public void setStatusBarTintEnabled(boolean enabled) {

134         mStatusBarTintEnabled = enabled;

135         if (mStatusBarAvailable) {

136             mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);

137         }

138     }

139 

140     /**

141      * set status bar darkmode

142      * @param darkmode

143      * @param activity

144      */

145     public void setStatusBarDarkMode(boolean darkmode, Activity activity) {

146         if (sIsMiuiV6) {

147             Class<? extends Window> clazz = activity.getWindow().getClass();

148             try {

149             int darkModeFlag = 0;

150             Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");

151             Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");

152             darkModeFlag = field.getInt(layoutParams);

153             Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);

154             extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);

155             } catch (Exception e) {

156                 e.printStackTrace();

157             }

158         }

159     }

160 

161     /**

162      * Enable tinting of the system navigation bar.

163      *

164      * If the platform does not have soft navigation keys, is running Jelly Bean

165      * or earlier, or translucent system UI modes have not been enabled in either

166      * the theme or via window flags, then this method does nothing.

167      *

168      * @param enabled True to enable tinting, false to disable it (default).

169      */

170     public void setNavigationBarTintEnabled(boolean enabled) {

171         mNavBarTintEnabled = enabled;

172         if (mNavBarAvailable) {

173             mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);

174         }

175     }

176 

177     /**

178      * Apply the specified color tint to all system UI bars.

179      *

180      * @param color The color of the background tint.

181      */

182     public void setTintColor(int color) {

183         setStatusBarTintColor(color);

184         setNavigationBarTintColor(color);

185     }

186 

187     /**

188      * Apply the specified drawable or color resource to all system UI bars.

189      *

190      * @param res The identifier of the resource.

191      */

192     public void setTintResource(int res) {

193         setStatusBarTintResource(res);

194         setNavigationBarTintResource(res);

195     }

196 

197     /**

198      * Apply the specified drawable to all system UI bars.

199      *

200      * @param drawable The drawable to use as the background, or null to remove it.

201      */

202     public void setTintDrawable(Drawable drawable) {

203         setStatusBarTintDrawable(drawable);

204         setNavigationBarTintDrawable(drawable);

205     }

206 

207     /**

208      * Apply the specified alpha to all system UI bars.

209      *

210      * @param alpha The alpha to use

211      */

212     public void setTintAlpha(float alpha) {

213         setStatusBarAlpha(alpha);

214         setNavigationBarAlpha(alpha);

215     }

216 

217     /**

218      * Apply the specified color tint to the system status bar.

219      *

220      * @param color The color of the background tint.

221      */

222     public void setStatusBarTintColor(int color) {

223         if (mStatusBarAvailable) {

224             mStatusBarTintView.setBackgroundColor(color);

225         }

226     }

227 

228     /**

229      * Apply the specified drawable or color resource to the system status bar.

230      *

231      * @param res The identifier of the resource.

232      */

233     public void setStatusBarTintResource(int res) {

234         if (mStatusBarAvailable) {

235             mStatusBarTintView.setBackgroundResource(res);

236         }

237     }

238 

239     /**

240      * Apply the specified drawable to the system status bar.

241      *

242      * @param drawable The drawable to use as the background, or null to remove it.

243      */

244     @SuppressWarnings("deprecation")

245     public void setStatusBarTintDrawable(Drawable drawable) {

246         if (mStatusBarAvailable) {

247             mStatusBarTintView.setBackgroundDrawable(drawable);

248         }

249     }

250 

251     /**

252      * Apply the specified alpha to the system status bar.

253      *

254      * @param alpha The alpha to use

255      */

256     @TargetApi(11)

257     public void setStatusBarAlpha(float alpha) {

258         if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

259             mStatusBarTintView.setAlpha(alpha);

260         }

261     }

262 

263     /**

264      * Apply the specified color tint to the system navigation bar.

265      *

266      * @param color The color of the background tint.

267      */

268     public void setNavigationBarTintColor(int color) {

269         if (mNavBarAvailable) {

270             mNavBarTintView.setBackgroundColor(color);

271         }

272     }

273 

274     /**

275      * Apply the specified drawable or color resource to the system navigation bar.

276      *

277      * @param res The identifier of the resource.

278      */

279     public void setNavigationBarTintResource(int res) {

280         if (mNavBarAvailable) {

281             mNavBarTintView.setBackgroundResource(res);

282         }

283     }

284 

285     /**

286      * Apply the specified drawable to the system navigation bar.

287      *

288      * @param drawable The drawable to use as the background, or null to remove it.

289      */

290     @SuppressWarnings("deprecation")

291     public void setNavigationBarTintDrawable(Drawable drawable) {

292         if (mNavBarAvailable) {

293             mNavBarTintView.setBackgroundDrawable(drawable);

294         }

295     }

296 

297     /**

298      * Apply the specified alpha to the system navigation bar.

299      *

300      * @param alpha The alpha to use

301      */

302     @TargetApi(11)

303     public void setNavigationBarAlpha(float alpha) {

304         if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

305             mNavBarTintView.setAlpha(alpha);

306         }

307     }

308 

309     /**

310      * Get the system bar configuration.

311      *

312      * @return The system bar configuration for the current device configuration.

313      */

314     public SystemBarConfig getConfig() {

315         return mConfig;

316     }

317 

318     /**

319      * Is tinting enabled for the system status bar?

320      *

321      * @return True if enabled, False otherwise.

322      */

323     public boolean isStatusBarTintEnabled() {

324         return mStatusBarTintEnabled;

325     }

326 

327     /**

328      * Is tinting enabled for the system navigation bar?

329      *

330      * @return True if enabled, False otherwise.

331      */

332     public boolean isNavBarTintEnabled() {

333         return mNavBarTintEnabled;

334     }

335 

336     private void setupStatusBarView(Context context, ViewGroup decorViewGroup) {

337         mStatusBarTintView = new View(context);

338         LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight());

339         params.gravity = Gravity.TOP;

340         if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) {

341             params.rightMargin = mConfig.getNavigationBarWidth();

342         }

343         mStatusBarTintView.setLayoutParams(params);

344         mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);

345         mStatusBarTintView.setVisibility(View.GONE);

346         decorViewGroup.addView(mStatusBarTintView);

347     }

348 

349     private void setupNavBarView(Context context, ViewGroup decorViewGroup) {

350         mNavBarTintView = new View(context);

351         LayoutParams params;

352         if (mConfig.isNavigationAtBottom()) {

353             params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight());

354             params.gravity = Gravity.BOTTOM;

355         } else {

356             params = new LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MATCH_PARENT);

357             params.gravity = Gravity.RIGHT;

358         }

359         mNavBarTintView.setLayoutParams(params);

360         mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);

361         mNavBarTintView.setVisibility(View.GONE);

362         decorViewGroup.addView(mNavBarTintView);

363     }

364 

365     /**

366      * Class which describes system bar sizing and other characteristics for the current

367      * device configuration.

368      *

369      */

370     public static class SystemBarConfig {

371 

372         private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";

373         private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";

374         private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";

375         private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";

376 

377         private final boolean mTranslucentStatusBar;

378         private final boolean mTranslucentNavBar;

379         private final int mStatusBarHeight;

380         private final int mActionBarHeight;

381         private final boolean mHasNavigationBar;

382         private final int mNavigationBarHeight;

383         private final int mNavigationBarWidth;

384         private final boolean mInPortrait;

385         private final float mSmallestWidthDp;

386 

387         private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) {

388             Resources res = activity.getResources();

389             mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);

390             mSmallestWidthDp = getSmallestWidthDp(activity);

391             mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);

392             mActionBarHeight = getActionBarHeight(activity);

393             mNavigationBarHeight = getNavigationBarHeight(activity);

394             mNavigationBarWidth = getNavigationBarWidth(activity);

395             mHasNavigationBar = (mNavigationBarHeight > 0);

396             mTranslucentStatusBar = translucentStatusBar;

397             mTranslucentNavBar = traslucentNavBar;

398         }

399 

400         @TargetApi(14)

401         private int getActionBarHeight(Context context) {

402             int result = 0;

403             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

404                 TypedValue tv = new TypedValue();

405                 context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);

406                 result = context.getResources().getDimensionPixelSize(tv.resourceId);

407             }

408             return result;

409         }

410 

411         @TargetApi(14)

412         private int getNavigationBarHeight(Context context) {

413             Resources res = context.getResources();

414             int result = 0;

415             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

416                 if (!ViewConfiguration.get(context).hasPermanentMenuKey()) {

417                     String key;

418                     if (mInPortrait) {

419                         key = NAV_BAR_HEIGHT_RES_NAME;

420                     } else {

421                         key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;

422                     }

423                     return getInternalDimensionSize(res, key);

424                 }

425             }

426             return result;

427         }

428 

429         @TargetApi(14)

430         private int getNavigationBarWidth(Context context) {

431             Resources res = context.getResources();

432             int result = 0;

433             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

434                 if (!ViewConfiguration.get(context).hasPermanentMenuKey()) {

435                     return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);

436                 }

437             }

438             return result;

439         }

440 

441         private int getInternalDimensionSize(Resources res, String key) {

442             int result = 0;

443             int resourceId = res.getIdentifier(key, "dimen", "android");

444             if (resourceId > 0) {

445                 result = res.getDimensionPixelSize(resourceId);

446             }

447             return result;

448         }

449 

450         @SuppressLint("NewApi")

451         private float getSmallestWidthDp(Activity activity) {

452             DisplayMetrics metrics = new DisplayMetrics();

453             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {

454                 activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);

455             } else {

456                 // TODO this is not correct, but we don't really care pre-kitkat

457                 activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

458             }

459             float widthDp = metrics.widthPixels / metrics.density;

460             float heightDp = metrics.heightPixels / metrics.density;

461             return Math.min(widthDp, heightDp);

462         }

463 

464         /**

465          * Should a navigation bar appear at the bottom of the screen in the current

466          * device configuration? A navigation bar may appear on the right side of

467          * the screen in certain configurations.

468          *

469          * @return True if navigation should appear at the bottom of the screen, False otherwise.

470          */

471         public boolean isNavigationAtBottom() {

472             return (mSmallestWidthDp >= 600 || mInPortrait);

473         }

474 

475         /**

476          * Get the height of the system status bar.

477          *

478          * @return The height of the status bar (in pixels).

479          */

480         public int getStatusBarHeight() {

481             return mStatusBarHeight;

482         }

483 

484         /**

485          * Get the height of the action bar.

486          *

487          * @return The height of the action bar (in pixels).

488          */

489         public int getActionBarHeight() {

490             return mActionBarHeight;

491         }

492 

493         /**

494          * Does this device have a system navigation bar?

495          *

496          * @return True if this device uses soft key navigation, False otherwise.

497          */

498         public boolean hasNavigtionBar() {

499             return mHasNavigationBar;

500         }

501 

502         /**

503          * Get the height of the system navigation bar.

504          *

505          * @return The height of the navigation bar (in pixels). If the device does not have

506          * soft navigation keys, this will always return 0.

507          */

508         public int getNavigationBarHeight() {

509             return mNavigationBarHeight;

510         }

511 

512         /**

513          * Get the width of the system navigation bar when it is placed vertically on the screen.

514          *

515          * @return The width of the navigation bar (in pixels). If the device does not have

516          * soft navigation keys, this will always return 0.

517          */

518         public int getNavigationBarWidth() {

519             return mNavigationBarWidth;

520         }

521 

522         /**

523          * Get the layout inset for any system UI that appears at the top of the screen.

524          *

525          * @param withActionBar True to include the height of the action bar, False otherwise.

526          * @return The layout inset (in pixels).

527          */

528         public int getPixelInsetTop(boolean withActionBar) {

529             return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0);

530         }

531 

532         /**

533          * Get the layout inset for any system UI that appears at the bottom of the screen.

534          *

535          * @return The layout inset (in pixels).

536          */

537         public int getPixelInsetBottom() {

538             if (mTranslucentNavBar && isNavigationAtBottom()) {

539                 return mNavigationBarHeight;

540             } else {

541                 return 0;

542             }

543         }

544 

545         /**

546          * Get the layout inset for any system UI that appears at the right of the screen.

547          *

548          * @return The layout inset (in pixels).

549          */

550         public int getPixelInsetRight() {

551             if (mTranslucentNavBar && !isNavigationAtBottom()) {

552                 return mNavigationBarWidth;

553             } else {

554                 return 0;

555             }

556         }

557 

558     }

559 

560 }

使用起来也很简单,在你的activity或者baseactivity的oncreate方法中加入以下代码:

1 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

2             setTranslucentStatus(true);

3         }

4         mTintManager = new SystemBarTintManager(this);

5         mTintManager.setStatusBarTintEnabled(true);

6         //使StatusBarTintView 和 actionbar的颜色保持一致,风格统一。

7         mTintManager.setStatusBarTintResource(R.color.navbar);

8         // 设置状态栏的文字颜色

9         mTintManager.setStatusBarDarkMode(false, this);

setTranslucentStatus方法

 1 @TargetApi(19)

 2     protected void setTranslucentStatus(boolean on) {

 3         Window win = getWindow();

 4         WindowManager.LayoutParams winParams = win.getAttributes();

 5         final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;

 6         if (on) {

 7             winParams.flags |= bits;

 8         } else {

 9             winParams.flags &= ~bits;

10         }

11         win.setAttributes(winParams);

12     }

然后需要在你的布局文件最外层添加以下代码

 1 android:fitsSystemWindows="true"

2 android:clipToPadding="false" 这个在设置主题的那里是设置为true的,注意区分

如果你只用了普通的activity,那么一切事情都已经结束了。但我做的司信项目,在主界面上用的是一个activitygroup,然后用tabhost添加了4个activity,这样的话会有一些出入,需要在activitygroup的方法上写上以上代码,activity继承了baseactivity,因此也加入了这些属性,会造成自定义的导航栏文字显示不全。

这个时候就再调用一下

mTintManager.setStatusBarTintEnabled(false);//把自定义的titlebar设置不显示

这样就可以了,效果是与之前的一样的,因此不再贴图。好处就是不会忽然闪一下之前的红色背景了。

你可能感兴趣的:(设置)