参考文章:
《Android 开发:Translucent System Bar 的最佳实践》
关于透明状态栏
仔细看了上面文章中的实现,发现不能完全满足项目需求,于是在上面项目的基础上做了一些修改,效果描述如下:
- 图片(非背景图)占用StatusBar显示
- 图片可以随页面滑动
- ActionBar和StatusBar随滑动距离透明度渐变
- 仅支持
API>19
静态效果:
动态效果:
原理
在API>19
的手机上,可以在styles中设置windowTranslucentStatus
属性使状态栏变透明,[1][同时Activity的布局也会占据原来StatusBar的位置]。
因为[1]的原因,ActionBar会上移和statusbar重叠,为了避免出现在种情况我们会考虑使用fitsSystemWindows,随之而来的问题就是图片不能显示在StatusBar下面了。这就是我在采用参考文章中的思路时遇到的问题,这个问题让我不得不考虑其它的实现方式。
回到问题的起点,设置windowTranslucentStatus
属性后,ActionBar占用了StatusBar的位置。 在这里放置一个占位的View,高度设置为StatusBar的高度不就可以了吗?
我最终采用的就是上面的思路,满足了产品的需求。下面是代码部分,在上面基础上加了ActionBar随滑动距离的渐变:
styles:
//values-v19/styles.xml
<style name="ImageTranslucentTheme"
parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
布局文件:
//layout/activity_image_translucent_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:toolbar="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/ban_size"
android:background="@mipmap/topinfo_ban_bg" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="1234456678898900"
android:textSize="200dp" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<LinearLayout
android:id="@+id/topbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="@+id/status_placeholder"
android:layout_width="match_parent"
android:layout_height="0dp" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
toolbar:navigationIcon="@mipmap/ic_drawer_home">
</android.support.v7.widget.Toolbar>
</LinearLayout>
</RelativeLayout>
编码:
public class ImageTranslucentBarActivity extends AppCompatActivity {
private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
private static final String TAG = ImageTranslucentBarActivity.class.getSimpleName();
private GradientDrawable gradientDrawable; //头部遮罩
private LinearLayout topbar;//标题栏+placeholder
private View placeholder;//占用statusbar的位置
private Toolbar toolbar;
private NestedScrollView scrollView;
private int banSize;
private int mActionBarHeight;
private int mStatusBarHeight;
private int bufferDistance;//缓冲距离
private int threshold;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_translucent_bar);
placeholder = findViewById(R.id.status_placeholder);
topbar = (LinearLayout) findViewById(R.id.topbar);
toolbar = (Toolbar) findViewById(R.id.toolbar);
scrollView = (NestedScrollView) findViewById(R.id.scrollView);
toolbar.inflateMenu(R.menu.base_toolbar_menu);
//StatusBar占位
mStatusBarHeight = getInternalDimensionSize(getResources(),
STATUS_BAR_HEIGHT_RES_NAME);
LayoutParams params = (LayoutParams) placeholder.getLayoutParams();
params.height = mStatusBarHeight;
placeholder.setLayoutParams(params);
//toolbar高度
mActionBarHeight = getActionBarHeight(this);
//图片高度
banSize = getResources().getDimensionPixelSize(R.dimen.ban_size);
bufferDistance = getResources()
.getDimensionPixelOffset(R.dimen.buffer_distance);
//头部遮罩,之所以写在代码里,是因为要实现随滑动距离变色
gradientDrawable = (GradientDrawable) getResources()
.getDrawable(R.drawable.gradient_bg);
topbar.setBackgroundDrawable(gradientDrawable);
threshold = banSize - mStatusBarHeight + bufferDistance;
scrollView.setOnScrollChangeListener(
new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v,
int scrollX,
int scrollY,
int oldScrollX,
int oldScrollY) {
if (scrollY <= threshold) {
float scale0 = Math.min(scrollY * 1.0f / (banSize - mStatusBarHeight
- mActionBarHeight), 1.0f);
float scale1 = Math.min(scrollY * 1.0f / (banSize - mStatusBarHeight), 1.0f);
int startColor = Color.argb((int) (255 * scale0), (int) (254 * scale0),
(int) (134 * scale0), (int) (158 * scale0));
int endColor = Color.argb((int) (255 * scale1), (int) (254 * scale1),
(int) (134 * scale1), (int) (158 * scale1));
int[] colors = new int[]{startColor, endColor};
gradientDrawable.setColors(colors);
topbar.setBackgroundDrawable(gradientDrawable);
}
}
});
}
@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;
}
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;
}
}
网友评论