专栏首页恩蓝脚本Android沉浸式状态栏 + actionBar渐变 + scrollView顶部伸缩效果

Android沉浸式状态栏 + actionBar渐变 + scrollView顶部伸缩效果

闲话不多说,直接上图。

给大家讲讲我的编程思想吧。

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

values

<style name="TranslucentTheme" parent="@style/AppTheme" 
</style 

values-19

<style name="TranslucentTheme" parent="@style/AppTheme" 
 <item name="android:windowTranslucentStatus" true</item 
 <item name="android:windowTranslucentNavigation" false</item 
</style 

values-V21

<style name="TranslucentTheme" parent="@style/AppTheme" 
 <item name="android:windowTranslucentStatus" true</item 
 <item name="android:windowTranslucentNavigation" false</item 
 <!-- v-21 中新增的属性 -- 
 <item name="android:statusBarColor" @android:color/transparent</item 
</style 

至于以上属性的含义及使用方式,就不多做解释了。

第二部分:actionBar渐变

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

直接给各位看代码

package test.com.widget; 
import android.content.Context; 
import android.text.TextUtils; 
import android.util.AttributeSet; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.LinearLayout; 
import android.widget.TextView; 
import test.com.R; 
import test.com.impl.ActionBarClickListener; 
/** 
* 支持渐变的 actionBar 
* Created by 晖仔(Milo) on 2016/12/28. 
* email:303767416@qq.com 
*/ 
public final class TranslucentActionBar extends LinearLayout { 
private View layRoot; 
private View vStatusBar; 
private View layLeft; 
private View layRight; 
public TextView tvTitle; 
private TextView tvLeft; 
private TextView tvRight; 
private View iconLeft; 
private View iconRight; 
public TranslucentActionBar(Context context) { 
this(context, null); 
} 
public TranslucentActionBar(Context context, AttributeSet attrs) { 
super(context, attrs); 
init(); 
} 
public TranslucentActionBar(Context context, AttributeSet attrs, int defStyleAttr) { 
super(context, attrs, defStyleAttr); 
} 
private void init() { 
setOrientation(HORIZONTAL); 
View contentView = inflate(getContext(), R.layout.actionbar_trans, this); 
layRoot = contentView.findViewById(R.id.lay_transroot); 
vStatusBar = contentView.findViewById(R.id.v_statusbar); 
tvTitle = (TextView) contentView.findViewById(R.id.tv_actionbar_title); 
tvLeft = (TextView) contentView.findViewById(R.id.tv_actionbar_left); 
tvRight = (TextView) contentView.findViewById(R.id.tv_actionbar_right); 
iconLeft = contentView.findViewById(R.id.iv_actionbar_left); 
iconRight = contentView.findViewById(R.id.v_actionbar_right); 
} 
/** 
* 设置状态栏高度 
* 
* @param statusBarHeight 
*/ 
public void setStatusBarHeight(int statusBarHeight) { 
ViewGroup.LayoutParams params = vStatusBar.getLayoutParams(); 
params.height = statusBarHeight; 
vStatusBar.setLayoutParams(params); 
} 
/** 
* 设置是否需要渐变 
*/ 
public void setNeedTranslucent() { 
setNeedTranslucent(true, false); 
} 
/** 
* 设置是否需要渐变,并且隐藏标题 
* 
* @param translucent 
*/ 
public void setNeedTranslucent(boolean translucent, boolean titleInitVisibile) { 
if (translucent) { 
layRoot.setBackgroundDrawable(null); 
} 
if (!titleInitVisibile) { 
tvTitle.setVisibility(View.GONE); 
} 
} 
/** 
* 设置标题 
* 
* @param strTitle 
*/ 
public void setTitle(String strTitle) { 
if (!TextUtils.isEmpty(strTitle)) { 
tvTitle.setText(strTitle); 
} else { 
tvTitle.setVisibility(View.GONE); 
} 
} 
/** 
* 设置数据 
* 
* @param strTitle 
* @param resIdLeft 
* @param strLeft 
* @param resIdRight 
* @param strRight 
* @param listener 
*/ 
public void setData(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) { 
if (!TextUtils.isEmpty(strTitle)) { 
tvTitle.setText(strTitle); 
} else { 
tvTitle.setVisibility(View.GONE); 
} 
if (!TextUtils.isEmpty(strLeft)) { 
tvLeft.setText(strLeft); 
tvLeft.setVisibility(View.VISIBLE); 
} else { 
tvLeft.setVisibility(View.GONE); 
} 
if (!TextUtils.isEmpty(strRight)) { 
tvRight.setText(strRight); 
tvRight.setVisibility(View.VISIBLE); 
} else { 
tvRight.setVisibility(View.GONE); 
} 
if (resIdLeft == 0) { 
iconLeft.setVisibility(View.GONE); 
} else { 
iconLeft.setBackgroundResource(resIdLeft); 
iconLeft.setVisibility(View.VISIBLE); 
} 
if (resIdRight == 0) { 
iconRight.setVisibility(View.GONE); 
} else { 
iconRight.setBackgroundResource(resIdRight); 
iconRight.setVisibility(View.VISIBLE); 
} 
if (listener != null) { 
layLeft = findViewById(R.id.lay_actionbar_left); 
layRight = findViewById(R.id.lay_actionbar_right); 
layLeft.setOnClickListener(new View.OnClickListener() { 
@Override 
public void onClick(View v) { 
listener.onLeftClick(); 
} 
}); 
layRight.setOnClickListener(new View.OnClickListener() { 
@Override 
public void onClick(View v) { 
listener.onRightClick(); 
} 
}); 
} 
} 
} 

下面是actionbar_trans.xml的代码

<?xml version="1.0" encoding="utf-8"?  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/lay_transroot" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:background="@color/colorPrimary" 
android:orientation="vertical"  
<View 
android:id="@+id/v_statusbar" 
android:layout_width="match_parent" 
android:layout_height="1.0dp" /  
<RelativeLayout 
android:layout_width="match_parent" 
android:layout_height="45dp" 
android:orientation="vertical"  
<RelativeLayout 
android:id="@+id/lay_actionbar_left" 
android:layout_width="100dp" 
android:layout_height="match_parent" 
android:orientation="horizontal"  
<ImageView 
android:id="@+id/iv_actionbar_left" 
android:layout_width="20dp" 
android:layout_height="20dp" 
android:layout_centerVertical="true" 
android:layout_marginLeft="10dp" 
android:background="@mipmap/ic_left_light" 
android:visibility="gone" /  
<TextView 
android:id="@+id/tv_actionbar_left" 
style="@style/text_white" 
android:layout_height="match_parent" 
android:layout_marginLeft="10dp" 
android:layout_toRightOf="@+id/iv_actionbar_left" 
android:gravity="center_vertical" 
android:maxLength="2" 
android:singleLine="true" 
android:text="返回" 
android:visibility="gone" /  
</RelativeLayout  
<TextView 
android:id="@+id/tv_actionbar_title" 
style="@style/text_white" 
android:layout_centerInParent="true" 
android:text="标题" 
android:textSize="16sp" /  
<RelativeLayout 
android:id="@+id/lay_actionbar_right" 
android:layout_width="100dp" 
android:layout_height="match_parent" 
android:layout_alignParentRight="true" 
android:gravity="right" 
android:orientation="horizontal"  
<View 
android:id="@+id/v_actionbar_right" 
android:layout_width="20dp" 
android:layout_height="20dp" 
android:layout_alignParentRight="true" 
android:layout_centerVertical="true" 
android:layout_marginRight="10dp" 
android:visibility="gone" /  
<TextView 
android:id="@+id/tv_actionbar_right" 
style="@style/text_white" 
android:layout_height="match_parent" 
android:layout_marginRight="10dp" 
android:layout_toLeftOf="@+id/v_actionbar_right" 
android:gravity="center_vertical|right" 
android:singleLine="true" 
android:visibility="gone" /  
</RelativeLayout  
</RelativeLayout  
</LinearLayout  

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

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

获取状态栏高度代码:

/** 
* 获取状态栏高度 
* 
* @return 
*/ 
public int getStatusBarHeight() { 
//获取status_bar_height资源的ID 
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); 
if (resourceId   0) { 
//根据资源ID获取响应的尺寸值 
return getResources().getDimensionPixelSize(resourceId); 
} 
return 0; 
} 

设置 statusbar高度:

/** 
* 设置状态栏高度 
* 
* @param statusBarHeight 
*/ 
public void setStatusBarHeight(int statusBarHeight) { 
ViewGroup.LayoutParams params = vStatusBar.getLayoutParams(); 
params.height = statusBarHeight; 
vStatusBar.setLayoutParams(params); 
} 

开启渐变:

/** 
* 设置是否需要渐变 
*/ 
public void setNeedTranslucent() { 
setNeedTranslucent(true, false); 
} 
/** 
* 设置是否需要渐变,并且隐藏标题 
* 
* @param translucent 
*/ 
public void setNeedTranslucent(boolean translucent, boolean titleInitVisibile) { 
if (translucent) { 
layRoot.setBackgroundDrawable(null); 
} 
if (!titleInitVisibile) { 
tvTitle.setVisibility(View.GONE); 
} 
} 

第三步:实现ScrollView顶部伸缩

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

package test.com.widget; 
import android.animation.ObjectAnimator; 
import android.animation.ValueAnimator; 
import android.content.Context; 
import android.graphics.Color; 
import android.support.annotation.ColorInt; 
import android.support.v4.graphics.ColorUtils; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.WindowManager; 
import android.widget.ScrollView; 
import test.com.R; 
import test.com.utils.SizeUtils; 
/** 
* Created by 晖仔(Milo) on 2017/2/13. 
* email:303767416@qq.com 
*/ 
public class TranslucentScrollView extends ScrollView { 
static final String TAG = "TranslucentScrollView"; 
//伸缩视图 
private View zoomView; 
//伸缩视图初始高度 
private int zoomViewInitHeight = 0; 
// 记录首次按下位置 
private float mFirstPosition = 0; 
// 是否正在放大 
private Boolean mScaling = false; 
//渐变的视图 
private View transView; 
//渐变颜色 
private int transColor = Color.WHITE; 
//渐变开始位置 
private int transStartY = 50; 
//渐变结束位置 
private int transEndY = 300; 
//渐变开始默认位置,Y轴,50dp 
private final int DFT_TRANSSTARTY = 50; 
//渐变结束默认位置,Y轴,300dp 
private final int DFT_TRANSENDY = 300; 
private TranslucentScrollView.TranslucentChangedListener translucentChangedListener; 
public interface TranslucentChangedListener { 
/** 
* 透明度变化,取值范围0-255 
* 
* @param transAlpha 
*/ 
void onTranslucentChanged(int transAlpha); 
} 
public TranslucentScrollView(Context context) { 
super(context); 
} 
public TranslucentScrollView(Context context, AttributeSet attrs) { 
super(context, attrs); 
} 
public TranslucentScrollView(Context context, AttributeSet attrs, int defStyleAttr) { 
super(context, attrs, defStyleAttr); 
} 
public void setTranslucentChangedListener(TranslucentScrollView.TranslucentChangedListener translucentChangedListener) { 
this.translucentChangedListener = translucentChangedListener; 
} 
/** 
* 设置伸缩视图 
* 
* @param zoomView 
*/ 
public void setPullZoomView(View zoomView) { 
this.zoomView = zoomView; 
zoomViewInitHeight = zoomView.getLayoutParams().height; 
if (zoomViewInitHeight == LayoutParams.MATCH_PARENT || zoomViewInitHeight == WindowManager.LayoutParams.WRAP_CONTENT) { 
zoomView.post(new Runnable() { 
@Override 
public void run() { 
zoomViewInitHeight = TranslucentScrollView.this.zoomView.getHeight(); 
} 
}); 
} 
} 
/** 
* 设置渐变视图 
* 
* @param transView 渐变的视图 
*/ 
public void setTransView(View transView) { 
setTransView(transView, getResources().getColor(R.color.colorPrimary), SizeUtils.dip2px(getContext(), DFT_TRANSSTARTY), SizeUtils.dip2px(getContext(), DFT_TRANSENDY)); 
} 
/** 
* 设置渐变视图 
* 
* @param transView 渐变的视图 
* @param transColor 渐变颜色 
* @param transEndY 渐变结束位置 
*/ 
public void setTransView(View transView, @ColorInt int transColor, int transStartY, int transEndY) { 
this.transView = transView; 
//初始视图-透明 
this.transView.setBackgroundColor(ColorUtils.setAlphaComponent(transColor, 0)); 
this.transStartY = transStartY; 
this.transEndY = transEndY; 
this.transColor = transColor; 
if (transStartY   transEndY) { 
throw new IllegalArgumentException("transStartY 不得大于 transEndY .. "); 
} 
} 
/** 
* 获取透明度 
* 
* @return 
*/ 
private int getTransAlpha() { 
float scrollY = getScrollY(); 
if (transStartY != 0) { 
if (scrollY <= transStartY) { 
return 0; 
} else if (scrollY  = transEndY) { 
return 255; 
} else { 
return (int) ((scrollY - transStartY) / (transEndY - transStartY) * 255); 
} 
} else { 
if (scrollY  = transEndY) { 
return 255; 
} 
return (int) ((transEndY - scrollY) / transEndY * 255); 
} 
} 
/** 
* 重置ZoomView 
*/ 
private void resetZoomView() { 
final ViewGroup.LayoutParams lp = zoomView.getLayoutParams(); 
final float h = zoomView.getLayoutParams().height;// ZoomView当前高度 
// 设置动画 
ValueAnimator anim = ObjectAnimator.ofFloat(0.0F, 1.0F).setDuration(200); 
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
@Override 
public void onAnimationUpdate(ValueAnimator animation) { 
float cVal = (Float) animation.getAnimatedValue(); 
lp.height = (int) (h - (h - zoomViewInitHeight) * cVal); 
zoomView.setLayoutParams(lp); 
} 
}); 
anim.start(); 
} 
@Override 
protected void onScrollChanged(int l, int t, int oldl, int oldt) { 
super.onScrollChanged(l, t, oldl, oldt); 
int transAlpha = getTransAlpha(); 
if (transView != null) { 
Log.d(TAG, "[onScrollChanged .. in ], 透明度 == " + transAlpha); 
transView.setBackgroundColor(ColorUtils.setAlphaComponent(transColor, transAlpha)); 
} 
if (translucentChangedListener != null) { 
translucentChangedListener.onTranslucentChanged(transAlpha); 
} 
} 
@Override 
public boolean onTouchEvent(MotionEvent event) { 
if (zoomView != null) { 
ViewGroup.LayoutParams params = zoomView.getLayoutParams(); 
switch (event.getAction()) { 
case MotionEvent.ACTION_UP: 
//手指离开后恢复图片 
mScaling = false; 
resetZoomView(); 
break; 
case MotionEvent.ACTION_MOVE: 
if (!mScaling) { 
if (getScrollY() == 0) { 
mFirstPosition = event.getY(); 
} else { 
break; 
} 
} 
int distance = (int) ((event.getY() - mFirstPosition) * 0.6); 
if (distance < 0) { 
break; 
} 
mScaling = true; 
params.height = zoomViewInitHeight + distance; 
Log.d(TAG, "params.height == " + params.height + ", zoomViewInitHeight == " + zoomViewInitHeight + ", distance == " + distance); 
zoomView.setLayoutParams(params); 
return true; 
} 
} 
return super.onTouchEvent(event); 
} 
} 

总结

以上所述是小编给大家介绍的Android沉浸式状态栏 + actionBar渐变 + scrollView顶部伸缩,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对ZaLou.Cn网站的支持!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • android实现左右侧滑菜单效果

    在android开发中,左右侧滑菜单的开发已成为我们现在开发的必备技术之一,再次之前,我没有做过相类似的demo,但是项目的开发有要求有这样的效果,而且大家都知...

    砸漏
  • Android单选按钮RadioButton的使用详解

    RadioButton是最普通的UI组件之一,继承了Button类,可以直接使用Button支持的各种属性和方法。

    砸漏
  • android短信管理器SmsManager实例详解

    本文实例为大家分享了android短信管理器SmsManager的具体代码,供大家参考,具体内容如下

    砸漏
  • Android Studio实现长方体表面积计算器

    本文实例为大家分享了Android Studio实现长方体、表面积计算器的具体代码,供大家参考,具体内容如下

    砸漏
  • 仿优酷Android客户端图片左右滑动(自动滑动)

    最终效果: ? 页面布局main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns...

    欢醉
  • Android ListView列表视图的使用方法

    当你要将某个从数据库或者文件中获得相当大的数据,在界面中向用户展示的时候,由于定义一个个视图比较麻烦,Android中提供了类似于数组的控件–ListView。

    砸漏
  • 仿今日头条顶部导航效果

     之前发现很多人在群里面、论坛上求网易新闻客户端的源码,之后我就去下了个网易新闻客户端和今日头条新闻客户端,发现他们的大体是一样的,于是在最近的空闲时间,便去琢...

    xiangzhihong
  • Android实现调用摄像头和相册的方法

    因为涉及到向SD卡写入数据,所有需要在AndroidMainfest.xml中声明响应权限

    砸漏
  • Android单选按钮RadioButton的使用详解

    RadioButton是最普通的UI组件之一,继承了Button类,可以直接使用Button支持的各种属性和方法。

    砸漏
  • Android自定义PopWindow带动画向下弹出效果

    本文实例为大家分享了PopWindow实现带动画向下弹出效果的具体代码,供大家参考,具体内容如下

    砸漏

扫码关注云+社区

领取腾讯云代金券