實現淘寶商品詳情頁toolbar 漸變、狀態列沉浸
阿新 • • 發佈:2019-02-17
<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);
}
}
}
}