当前位置:   article > 正文

Android沉浸式状态栏 + actionBar透明渐变 + scrollView顶部伸缩_android沉浸式状态栏和背景图拉伸

android沉浸式状态栏和背景图拉伸

闲话不多说,直接上图。

 

如果只是在项目中使用,不需要关心实现,直接访问GitHub即可。

GitHub地址:https://github.com/yanjunhui2014/TranslucentScrollView

 

如果对编程思想想要了解的,请继续往下读。

 

第一部分:沉浸式状态栏(API-Level 19, Android4.4 KitKat 之后加入的东西),而且在Api-Level 21版本中新增了一个属性(下面会说到)。所以,style文件应该声明三份。

 

 

 

values

 

  1. <style name="TranslucentTheme" parent="@style/AppTheme">
  2. </style>

 

values-19

 

  1. <style name="TranslucentTheme" parent="@style/AppTheme">
  2. <item name="android:windowTranslucentStatus">true</item>
  3. <item name="android:windowTranslucentNavigation">false</item>
  4. </style>

 

values-V21

 

  1. <style name="TranslucentTheme" parent="@style/AppTheme">
  2. <item name="android:windowTranslucentStatus">true</item>
  3. <item name="android:windowTranslucentNavigation">false</item>
  4. <!-- v-21 中新增的属性 -->
  5. <item name="android:statusBarColor">@android:color/transparent</item>
  6. </style>

 

 

至于以上属性的含义及使用方式,就不多做解释了。详细可参见 http://blog.csdn.net/fan7983377/article/details/51604657

 

第二部分:actionBar渐变

 

因为要实现actionBar渐变,所以我没有使用系统的actionBar。而是自定义了一个继承自LinearLayout的ViewGroup。

直接给各位看代码

 

  1. package test.com.widget;
  2. import android.content.Context;
  3. import android.text.TextUtils;
  4. import android.util.AttributeSet;
  5. import android.view.View;
  6. import android.view.ViewGroup;
  7. import android.widget.LinearLayout;
  8. import android.widget.TextView;
  9. import test.com.R;
  10. import test.com.impl.ActionBarClickListener;
  11. /**
  12. * 支持渐变的 actionBar
  13. * Created by 晖仔(Milo) on 2016/12/28.
  14. * email:303767416@qq.com
  15. */
  16. public final class TranslucentActionBar extends LinearLayout {
  17. private View layRoot;
  18. private View vStatusBar;
  19. private View layLeft;
  20. private View layRight;
  21. public TextView tvTitle;
  22. private TextView tvLeft;
  23. private TextView tvRight;
  24. private View iconLeft;
  25. private View iconRight;
  26. public TranslucentActionBar(Context context) {
  27. this(context, null);
  28. }
  29. public TranslucentActionBar(Context context, AttributeSet attrs) {
  30. super(context, attrs);
  31. init();
  32. }
  33. public TranslucentActionBar(Context context, AttributeSet attrs, int defStyleAttr) {
  34. super(context, attrs, defStyleAttr);
  35. }
  36. private void init() {
  37. setOrientation(HORIZONTAL);
  38. View contentView = inflate(getContext(), R.layout.actionbar_trans, this);
  39. layRoot = contentView.findViewById(R.id.lay_transroot);
  40. vStatusBar = contentView.findViewById(R.id.v_statusbar);
  41. tvTitle = (TextView) contentView.findViewById(R.id.tv_actionbar_title);
  42. tvLeft = (TextView) contentView.findViewById(R.id.tv_actionbar_left);
  43. tvRight = (TextView) contentView.findViewById(R.id.tv_actionbar_right);
  44. iconLeft = contentView.findViewById(R.id.iv_actionbar_left);
  45. iconRight = contentView.findViewById(R.id.v_actionbar_right);
  46. }
  47. /**
  48. * 设置状态栏高度
  49. *
  50. * @param statusBarHeight
  51. */
  52. public void setStatusBarHeight(int statusBarHeight) {
  53. ViewGroup.LayoutParams params = vStatusBar.getLayoutParams();
  54. params.height = statusBarHeight;
  55. vStatusBar.setLayoutParams(params);
  56. }
  57. /**
  58. * 设置是否需要渐变
  59. */
  60. public void setNeedTranslucent() {
  61. setNeedTranslucent(true, false);
  62. }
  63. /**
  64. * 设置是否需要渐变,并且隐藏标题
  65. *
  66. * @param translucent
  67. */
  68. public void setNeedTranslucent(boolean translucent, boolean titleInitVisibile) {
  69. if (translucent) {
  70. layRoot.setBackgroundDrawable(null);
  71. }
  72. if (!titleInitVisibile) {
  73. tvTitle.setVisibility(View.GONE);
  74. }
  75. }
  76. /**
  77. * 设置标题
  78. *
  79. * @param strTitle
  80. */
  81. public void setTitle(String strTitle) {
  82. if (!TextUtils.isEmpty(strTitle)) {
  83. tvTitle.setText(strTitle);
  84. } else {
  85. tvTitle.setVisibility(View.GONE);
  86. }
  87. }
  88. /**
  89. * 设置数据
  90. *
  91. * @param strTitle
  92. * @param resIdLeft
  93. * @param strLeft
  94. * @param resIdRight
  95. * @param strRight
  96. * @param listener
  97. */
  98. public void setData(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) {
  99. if (!TextUtils.isEmpty(strTitle)) {
  100. tvTitle.setText(strTitle);
  101. } else {
  102. tvTitle.setVisibility(View.GONE);
  103. }
  104. if (!TextUtils.isEmpty(strLeft)) {
  105. tvLeft.setText(strLeft);
  106. tvLeft.setVisibility(View.VISIBLE);
  107. } else {
  108. tvLeft.setVisibility(View.GONE);
  109. }
  110. if (!TextUtils.isEmpty(strRight)) {
  111. tvRight.setText(strRight);
  112. tvRight.setVisibility(View.VISIBLE);
  113. } else {
  114. tvRight.setVisibility(View.GONE);
  115. }
  116. if (resIdLeft == 0) {
  117. iconLeft.setVisibility(View.GONE);
  118. } else {
  119. iconLeft.setBackgroundResource(resIdLeft);
  120. iconLeft.setVisibility(View.VISIBLE);
  121. }
  122. if (resIdRight == 0) {
  123. iconRight.setVisibility(View.GONE);
  124. } else {
  125. iconRight.setBackgroundResource(resIdRight);
  126. iconRight.setVisibility(View.VISIBLE);
  127. }
  128. if (listener != null) {
  129. layLeft = findViewById(R.id.lay_actionbar_left);
  130. layRight = findViewById(R.id.lay_actionbar_right);
  131. layLeft.setOnClickListener(new View.OnClickListener() {
  132. @Override
  133. public void onClick(View v) {
  134. listener.onLeftClick();
  135. }
  136. });
  137. layRight.setOnClickListener(new View.OnClickListener() {
  138. @Override
  139. public void onClick(View v) {
  140. listener.onRightClick();
  141. }
  142. });
  143. }
  144. }
  145. }

 

 

下面是actionbar_trans.xml的代码

 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/lay_transroot"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:background="@color/colorPrimary"
  7. android:orientation="vertical">
  8. <View
  9. android:id="@+id/v_statusbar"
  10. android:layout_width="match_parent"
  11. android:layout_height="1.0dp" />
  12. <RelativeLayout
  13. android:layout_width="match_parent"
  14. android:layout_height="45dp"
  15. android:orientation="vertical">
  16. <RelativeLayout
  17. android:id="@+id/lay_actionbar_left"
  18. android:layout_width="100dp"
  19. android:layout_height="match_parent"
  20. android:orientation="horizontal">
  21. <ImageView
  22. android:id="@+id/iv_actionbar_left"
  23. android:layout_width="20dp"
  24. android:layout_height="20dp"
  25. android:layout_centerVertical="true"
  26. android:layout_marginLeft="10dp"
  27. android:background="@mipmap/ic_left_light"
  28. android:visibility="gone" />
  29. <TextView
  30. android:id="@+id/tv_actionbar_left"
  31. style="@style/text_white"
  32. android:layout_height="match_parent"
  33. android:layout_marginLeft="10dp"
  34. android:layout_toRightOf="@+id/iv_actionbar_left"
  35. android:gravity="center_vertical"
  36. android:maxLength="2"
  37. android:singleLine="true"
  38. android:text="返回"
  39. android:visibility="gone" />
  40. </RelativeLayout>
  41. <TextView
  42. android:id="@+id/tv_actionbar_title"
  43. style="@style/text_white"
  44. android:layout_centerInParent="true"
  45. android:text="标题"
  46. android:textSize="16sp" />
  47. <RelativeLayout
  48. android:id="@+id/lay_actionbar_right"
  49. android:layout_width="100dp"
  50. android:layout_height="match_parent"
  51. android:layout_alignParentRight="true"
  52. android:gravity="right"
  53. android:orientation="horizontal">
  54. <View
  55. android:id="@+id/v_actionbar_right"
  56. android:layout_width="20dp"
  57. android:layout_height="20dp"
  58. android:layout_alignParentRight="true"
  59. android:layout_centerVertical="true"
  60. android:layout_marginRight="10dp"
  61. android:visibility="gone" />
  62. <TextView
  63. android:id="@+id/tv_actionbar_right"
  64. style="@style/text_white"
  65. android:layout_height="match_parent"
  66. android:layout_marginRight="10dp"
  67. android:layout_toLeftOf="@+id/v_actionbar_right"
  68. android:gravity="center_vertical|right"
  69. android:singleLine="true"
  70. android:visibility="gone" />
  71. </RelativeLayout>
  72. </RelativeLayout>
  73. </LinearLayout>


这里我即没有用到 android:fitsSystemWindows="true" 属性,也没有用到 StatusBarUtils ,因为我发现使用的时候很容易造成兼容问题。

 

所以,我的做法是声明了一个高度为0.0dp的 statusbar,背景为透明,然后获取状态栏高度并赋值到它上,来实现兼容。事实证明,这样做的兼容效果最好。

 

获取状态栏高度代码:

 

  1. /**
  2. * 获取状态栏高度
  3. *
  4. * @return
  5. */
  6. public int getStatusBarHeight() {
  7. //获取status_bar_height资源的ID
  8. int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
  9. if (resourceId > 0) {
  10. //根据资源ID获取响应的尺寸值
  11. return getResources().getDimensionPixelSize(resourceId);
  12. }
  13. return 0;
  14. }


设置 statusbar高度:

 

 

  1. /**
  2. * 设置状态栏高度
  3. *
  4. * @param statusBarHeight
  5. */
  6. public void setStatusBarHeight(int statusBarHeight) {
  7. ViewGroup.LayoutParams params = vStatusBar.getLayoutParams();
  8. params.height = statusBarHeight;
  9. vStatusBar.setLayoutParams(params);
  10. }


开启渐变:

 

 

  1. /**
  2. * 设置是否需要渐变
  3. */
  4. public void setNeedTranslucent() {
  5. setNeedTranslucent(true, false);
  6. }
  7. /**
  8. * 设置是否需要渐变,并且隐藏标题
  9. *
  10. * @param translucent
  11. */
  12. public void setNeedTranslucent(boolean translucent, boolean titleInitVisibile) {
  13. if (translucent) {
  14. layRoot.setBackgroundDrawable(null);
  15. }
  16. if (!titleInitVisibile) {
  17. tvTitle.setVisibility(View.GONE);
  18. }
  19. }

 

 

 

 

 

第三步:实现ScrollView顶部伸缩

到了这里,必须得说一下,因为是个人项目中用到,所以并没有把功能做的很强大,本人都是以最简单、有效的方式实现的。所以,代码并不像gitHub上那些被下载很多次的开源项目一样,有很高的扩展性。

时间关系,我直接贴代码吧,代码里我都写了注释的。

 

  1. package test.com.widget;
  2. import android.animation.ObjectAnimator;
  3. import android.animation.ValueAnimator;
  4. import android.content.Context;
  5. import android.graphics.Color;
  6. import android.support.annotation.ColorInt;
  7. import android.support.v4.graphics.ColorUtils;
  8. import android.util.AttributeSet;
  9. import android.util.Log;
  10. import android.view.MotionEvent;
  11. import android.view.View;
  12. import android.view.ViewGroup;
  13. import android.view.WindowManager;
  14. import android.widget.ScrollView;
  15. import test.com.R;
  16. import test.com.utils.SizeUtils;
  17. /**
  18. * Created by 晖仔(Milo) on 2017/2/13.
  19. * email:303767416@qq.com
  20. */
  21. public class TranslucentScrollView extends ScrollView {
  22. static final String TAG = "TranslucentScrollView";
  23. //伸缩视图
  24. private View zoomView;
  25. //伸缩视图初始高度
  26. private int zoomViewInitHeight = 0;
  27. // 记录首次按下位置
  28. private float mFirstPosition = 0;
  29. // 是否正在放大
  30. private Boolean mScaling = false;
  31. //渐变的视图
  32. private View transView;
  33. //渐变颜色
  34. private int transColor = Color.WHITE;
  35. //渐变开始位置
  36. private int transStartY = 50;
  37. //渐变结束位置
  38. private int transEndY = 300;
  39. //渐变开始默认位置,Y轴,50dp
  40. private final int DFT_TRANSSTARTY = 50;
  41. //渐变结束默认位置,Y轴,300dp
  42. private final int DFT_TRANSENDY = 300;
  43. private TranslucentScrollView.TranslucentChangedListener translucentChangedListener;
  44. public interface TranslucentChangedListener {
  45. /**
  46. * 透明度变化,取值范围0-255
  47. *
  48. * @param transAlpha
  49. */
  50. void onTranslucentChanged(int transAlpha);
  51. }
  52. public TranslucentScrollView(Context context) {
  53. super(context);
  54. }
  55. public TranslucentScrollView(Context context, AttributeSet attrs) {
  56. super(context, attrs);
  57. }
  58. public TranslucentScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
  59. super(context, attrs, defStyleAttr);
  60. }
  61. public void setTranslucentChangedListener(TranslucentScrollView.TranslucentChangedListener translucentChangedListener) {
  62. this.translucentChangedListener = translucentChangedListener;
  63. }
  64. /**
  65. * 设置伸缩视图
  66. *
  67. * @param zoomView
  68. */
  69. public void setPullZoomView(View zoomView) {
  70. this.zoomView = zoomView;
  71. zoomViewInitHeight = zoomView.getLayoutParams().height;
  72. if (zoomViewInitHeight == LayoutParams.MATCH_PARENT || zoomViewInitHeight == WindowManager.LayoutParams.WRAP_CONTENT) {
  73. zoomView.post(new Runnable() {
  74. @Override
  75. public void run() {
  76. zoomViewInitHeight = TranslucentScrollView.this.zoomView.getHeight();
  77. }
  78. });
  79. }
  80. }
  81. /**
  82. * 设置渐变视图
  83. *
  84. * @param transView 渐变的视图
  85. */
  86. public void setTransView(View transView) {
  87. setTransView(transView, getResources().getColor(R.color.colorPrimary), SizeUtils.dip2px(getContext(), DFT_TRANSSTARTY), SizeUtils.dip2px(getContext(), DFT_TRANSENDY));
  88. }
  89. /**
  90. * 设置渐变视图
  91. *
  92. * @param transView 渐变的视图
  93. * @param transColor 渐变颜色
  94. * @param transEndY 渐变结束位置
  95. */
  96. public void setTransView(View transView, @ColorInt int transColor, int transStartY, int transEndY) {
  97. this.transView = transView;
  98. //初始视图-透明
  99. this.transView.setBackgroundColor(ColorUtils.setAlphaComponent(transColor, 0));
  100. this.transStartY = transStartY;
  101. this.transEndY = transEndY;
  102. this.transColor = transColor;
  103. if (transStartY > transEndY) {
  104. throw new IllegalArgumentException("transStartY 不得大于 transEndY .. ");
  105. }
  106. }
  107. /**
  108. * 获取透明度
  109. *
  110. * @return
  111. */
  112. private int getTransAlpha() {
  113. float scrollY = getScrollY();
  114. if (transStartY != 0) {
  115. if (scrollY <= transStartY) {
  116. return 0;
  117. } else if (scrollY >= transEndY) {
  118. return 255;
  119. } else {
  120. return (int) ((scrollY - transStartY) / (transEndY - transStartY) * 255);
  121. }
  122. } else {
  123. if (scrollY >= transEndY) {
  124. return 255;
  125. }
  126. return (int) ((transEndY - scrollY) / transEndY * 255);
  127. }
  128. }
  129. /**
  130. * 重置ZoomView
  131. */
  132. private void resetZoomView() {
  133. final ViewGroup.LayoutParams lp = zoomView.getLayoutParams();
  134. final float h = zoomView.getLayoutParams().height;// ZoomView当前高度
  135. // 设置动画
  136. ValueAnimator anim = ObjectAnimator.ofFloat(0.0F, 1.0F).setDuration(200);
  137. anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  138. @Override
  139. public void onAnimationUpdate(ValueAnimator animation) {
  140. float cVal = (Float) animation.getAnimatedValue();
  141. lp.height = (int) (h - (h - zoomViewInitHeight) * cVal);
  142. zoomView.setLayoutParams(lp);
  143. }
  144. });
  145. anim.start();
  146. }
  147. @Override
  148. protected void onScrollChanged(int l, int t, int oldl, int oldt) {
  149. super.onScrollChanged(l, t, oldl, oldt);
  150. int transAlpha = getTransAlpha();
  151. if (transView != null) {
  152. Log.d(TAG, "[onScrollChanged .. in ], 透明度 == " + transAlpha);
  153. transView.setBackgroundColor(ColorUtils.setAlphaComponent(transColor, transAlpha));
  154. }
  155. if (translucentChangedListener != null) {
  156. translucentChangedListener.onTranslucentChanged(transAlpha);
  157. }
  158. }
  159. @Override
  160. public boolean onTouchEvent(MotionEvent event) {
  161. if (zoomView != null) {
  162. ViewGroup.LayoutParams params = zoomView.getLayoutParams();
  163. switch (event.getAction()) {
  164. case MotionEvent.ACTION_UP:
  165. //手指离开后恢复图片
  166. mScaling = false;
  167. resetZoomView();
  168. break;
  169. case MotionEvent.ACTION_MOVE:
  170. if (!mScaling) {
  171. if (getScrollY() == 0) {
  172. mFirstPosition = event.getY();
  173. } else {
  174. break;
  175. }
  176. }
  177. int distance = (int) ((event.getY() - mFirstPosition) * 0.6);
  178. if (distance < 0) {
  179. break;
  180. }
  181. mScaling = true;
  182. params.height = zoomViewInitHeight + distance;
  183. Log.d(TAG, "params.height == " + params.height + ", zoomViewInitHeight == " + zoomViewInitHeight + ", distance == " + distance);
  184. zoomView.setLayoutParams(params);
  185. return true;
  186. }
  187. }
  188. return super.onTouchEvent(event);
  189. }
  190. }

 

 

 

 

原创不易,转载请附上本文地址:

 

 

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号