实现淘宝商品详情页toolbar 渐变、状态栏沉浸

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">	</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">本人做的项目是某传统行业的一款电商产品,项目中有的商品详情页需要和淘宝商品详情页类似的效果,就是实现toolbar和状态栏 更加页面的滚动实习透明度的渐变</span>

其实和某宝还有点差距 ,毕竟 我们是在H5页面去做的这种效果,接下来我说说具体实现。

这个h5页 只有title bar (toolbar)是本地 然后下面是webview,通过重写webview 的onscrollChangedListener() 方法。而onscrollChangedListener 的权限是protected 所有只有继承Webview 如下

public class CustomWebview extends WebView {
  public ScrollChangeListener mChangeListener;

  public CustomWebview(Context context) {
    super(context);
  }

  public CustomWebview(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }

  public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr,
                       int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
  }

  @Override
  protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    super.onScrollChanged(l, t, oldl, oldt);

    if (mChangeListener != null) {
      mChangeListener.onScrollChanged(l, t, oldl, oldt);
    }
  }

  public void setOnScrollChangeListener(ScrollChangeListener listener) {
    mChangeListener = listener;

  }

  interface ScrollChangeListener {
    void onScrollChanged(int l, int t, int oldl, int oldt);
  }
}
然后 在fragment里面实例化这个控件 ,因为我们的H5fragment是个基类 所以 就写了一个空的 方法 供子类继承重写



  private void initWebViewScrollChangeListener() {
    if (mWebView instanceof CustomWebview) {
      ((CustomWebview) mWebView)
          .setOnScrollChangeListener(new CustomWebview.ScrollChangeListener() {
            @Override
            public void onScrollChanged(int l, int t, int oldl, int oldt) {
              onWebViewScrollChanged(l, t, oldl, oldt);//这个是fragment里面的一个空的方法

            }
          });
    }
  }

这儿解释一下 我们架构 都是一个activity 嵌套一个fragment,所有的业务逻辑都在fragment里面去做。toolbar的操作是在activity里面进行的


activity的代码 一些说明我就写在代码的注释里面了

public class ShadowH5Activity extends H5Activity {
  private ShadowH5Fragment mFlashBuyH5Fragment;
  private SystemBarTintManager mTintManager;
  private CommonTitleView mTitleView;// 虽然用的toolbar,但是在我们项目中他只是个容器,比如这个view就是 真正的一个有返回箭头 和title的view

//可以自定义view的样式 在这里 我就是操作的这个view整体background的透明度 ,

  @Override
  protected void onCreate(Bundle onSaveInstanceState) {
    super.onCreate(onSaveInstanceState);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//特别说明一下 沉浸式效果只有在sdk19以上的版本才有,以下的没有
      showStatusBar();
    }
  }


  @Override
  public BaseFragment getFragment() {
    mFlashBuyH5Fragment = (ShadowH5Fragment) Fragment.instantiate(this,
        ShadowH5Fragment.class.getName(), getIntent().getExtras());
    return mFlashBuyH5Fragment;
  }

  @Override
  protected int getLayoutId() {
    return R.layout.shadow_tool_bar_h5_fragment_activity;//下面会有布局的代码
  }



  @Override
  protected void customizeToolbar(Toolbar toolbar) {
    setToolbarMarginTop(toolbar);
  }

  /**
   *
   * @param alpha 0~255
   */ 背景的透明度
  public void setTitleViewBacGroundAlpha(int alpha) {
    if (mTitleView != null && mTitleView.getBackground() != null)
      mTitleView.getBackground().setAlpha(alpha);
  }

  @Override
  protected TitleContainer getMyTitleContainer() {
    mTitleView = CommonTitleView.newInstance(this);//自定义一个view 不过 我还是复用的老的view 在这个 我想拿到这个view的对象 所以重写了
    return mTitleView;
  }

  /**
   *
   * @param alpha 0~1 控制title的透明度
   */
  public void setTitleAlpha(float alpha) {
    if (mTitleView != null && mTitleView.getTitle() != null) {
      mTitleView.getTitle().setAlpha(alpha);
    }
  }

  /**
   * 兼容性问题
   * 
   * @param toolbar
   */
  @TargetApi(19)
  private void setToolbarMarginTop(Toolbar toolbar) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//前面说了,版本19以上 的会有状太栏 渐变的效果,因为我吧整个页面全屏之后
      RelativeLayout.LayoutParams params =// statusBar 就隐藏了,但是我会把它show出来 ,此时toolbar和statusbar就会重叠,所以我给toolbar设置
          new RelativeLayout.LayoutParams(toolbar.getLayoutParams());//marginTop的属性,正好距离顶部一个statusbar的高度,=
      params.setMargins(0, getStatusBarHeight(), 0, 0);
      toolbar.setLayoutParams(params);
    }
  }


  @Override
  protected void initWindow() {重写基类的方法 实现沉浸式statusbar 蓝色的
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
      mTintManager = new SystemBarTintManager(this);
      mTintManager.setStatusBarTintEnabled(true);
      mTintManager.setTintColor(getResources().getColor(R.color.theme_blue));
    }

  }

  /**
   *
   * @return 状态栏高度
   */
  public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
      result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
  }

  public void setStatusBarAlpha(float statusBarAlpha) {
    if (mTintManager != null) {
      mTintManager.setTintAlpha(statusBarAlpha);
    }
  }

  /**
   * 隐藏状态栏
   */
  private void hideStatusBar() {
    WindowManager.LayoutParams attrs = getWindow().getAttributes();
    attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
    getWindow().setAttributes(attrs);
  }

  /**
   * 在全屏状态下 显示状态栏 (这种显示出来的statusbar 不会导致整个页面重绘)
   */
  private void showStatusBar() {
    WindowManager.LayoutParams attrs = getWindow().getAttributes();
    attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
    getWindow().setAttributes(attrs);
  }

}

xml布局

<?xml version="1.0" encoding="utf-8"?>
<xxx.sliding.SlidingLayout
    android:id="@+id/sliding_pane_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/transparent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <FrameLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/default_background"/>

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@android:color/transparent"/>

    </RelativeLayout>

</xxx.sliding.SlidingLayout>
fragment  的代码如下


public class ShadowH5Fragment extends H5Fragment {
  private ShadowH5Activity mActivity;
  private static final float SCROLL_LIMIT = 300f;//滑动的距离
  private static final float sDEFAULT_ALPHA = 0;//默认的透明度

  @Override
  protected void onInflated(View contentView, Bundle savedInstanceState) {
    super.onInflated(contentView, savedInstanceState);
    initViewAlpha();
  }

  private void initViewAlpha() {
    if (getActivity() != null) {
      if (getActivity() instanceof ShadowH5Activity) {
        mActivity = (ShadowH5Activity) getActivity();
        mActivity.setTitleViewBacGroundAlpha((int) sDEFAULT_ALPHA);
        mActivity.setTitleAlpha(sDEFAULT_ALPHA);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
          mActivity.setStatusBarAlpha(sDEFAULT_ALPHA);
        }
      }
    }
  }

  @Override
  protected void onWebViewScrollChanged(int l, int t, int oldl, int oldt) {
    if (mActivity != null) {
      float castT = t;
      if (t < SCROLL_LIMIT) {
        float progress = (castT / SCROLL_LIMIT);
        progress = progress > 0 ? progress : 0;
        mActivity.setTitleViewBacGroundAlpha((int) (progress * 255));
        mActivity.setTitleAlpha(progress);
        mActivity.setStatusBarAlpha(progress);
      } else {
        mActivity.setTitleViewBacGroundAlpha(255);
        mActivity.setTitleAlpha(1);
        mActivity.setStatusBarAlpha(1);
      }

    }
  }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值