Android   发布时间:2022-04-28  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了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>

至于以上属性的含义及使用方式,就不多做解释了。详细可参见 https://www.oudahe.com/p/26557/

第二部分: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://scheR_264_11845@as.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; 
 //渐变开始@L_673_30@认位置,Y轴,50dp 
 private final int DFT_TRANSSTARTY = 50; 
 //渐变结束@L_673_30@认位置,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,attrs); 
 } 
 public TranslucentScrollView(Context context,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),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顶部伸缩,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持

大佬总结

以上是大佬教程为你收集整理的Android沉浸式状态栏 + actionBar渐变 + scrollView顶部伸缩效果全部内容,希望文章能够帮你解决Android沉浸式状态栏 + actionBar渐变 + scrollView顶部伸缩效果所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。