如何在 Webview 中向下滚动时隐藏操作栏/工具栏

Posted

技术标签:

【中文标题】如何在 Webview 中向下滚动时隐藏操作栏/工具栏【英文标题】:How to Hide ActionBar/Toolbar While Scrolling Down in Webview 【发布时间】:2015-04-30 11:41:51 【问题描述】:

在 Google chrome 和 Play 商店中。该应用程序可以在滚动时隐藏操作栏,并允许用户方便地浏览。请帮我这样做。

我在 webview 中使用了 onTouchListener,它不起作用。

mWebView.setOnTouchListener(new View.OnTouchListener() 
            @Override
            public boolean onTouch(View v, MotionEvent event) 
                switch (event.getAction()) 
                    case MotionEvent.ACTION_DOWN:
                        getSupportActionBar().show();
                            break;
                    case MotionEvent.ACTION_UP:
                        getSupportActionBar().hide();
                            break;
                    default: break;
                
                return false;
            
        );

提前致谢

【问题讨论】:

隐藏操作栏的例子是here 此示例显示线性布局。如何在 webview 中实现这一点 这里有一个例子[***.com/questions/14752523/… 【参考方案1】:

您可以使用设计库的CoordinatorLayoutNestedScrollView 并在Toolbar 上设置app:layout_scrollFlags 来执行此操作,而无需任何Java 代码。这是你如何做到的。

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_
android:layout_>

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_
    android:layout_
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_
        android:layout_
        android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.AppBarLayout>

<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_
    android:layout_
    android:layout_gravity="fill_vertical"
   android:fillViewport="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <WebView
        android:id="@+id/webview"
        android:layout_
        android:layout_/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

一旦掌握了窍门,您就可以使用不同的 layout_scrollFlags 和 fitSystemWindows 行为。

【讨论】:

这很好用,但是你通过手势松开了“缩放”。有没有办法在这个解决方案中再次获得它?谢谢 有些人可能会发现有必要将android:fillViewport="true" 添加到NestedScrollView 以使其占据其容器的全部可用高度。奇怪的是,android:layout_gravity="fill_vertical" 在所有情况下都不足以实现这一目标。 它按预期工作,出现此错误“java.lang.IllegalStateException:无法为 WebView 创建层,大小 1200x17076 超过最大大小 16384”。有什么解决办法吗? 添加新布局会降低性能。这不是正确的解决方案。至于你的问题@Sudarshan,它正在发生,因为它会创建全尺寸的网页视图(与网页相同)并尝试渲染它。因此,您将失去 webview 优化,其中仅呈现页面的一部分。我不建议使用此解决方案。 在 ScrollView 中使用 Webview 的错误做法,跳转链接不起作用。【参考方案2】:

我已经通过CustomWebViewGestureDetector 实现了:

CustomWebView.java

public class CustomWebView extends WebView 
    private GestureDetector gestureDetector;
    public CustomWebView(Context context) 
        super(context);
    
    public CustomWebView(Context context, AttributeSet attrs) 
        super(context, attrs);
    
    public CustomWebView(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);
    
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) 
        super.onScrollChanged(l, t, oldl, oldt);
    

    @Override
    public boolean onTouchEvent(MotionEvent ev) 
        return gestureDetector.onTouchEvent(ev) || super.onTouchEvent(ev);
    

    public void setGestureDetector(GestureDetector gestureDetector) 
        this.gestureDetector = gestureDetector;
    

web_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_
    android:layout_
    android:background="@android:color/transparent"
    android:orientation="vertical">

   <com.customview.CustomWebView
            android:id="@+id/customWebView"
            android:layout_
            android:layout_
            android:focusable="true" />

</LinearLayout>

CustomeGestureDetector 用于手势检测的 clss(我已在 Fragment 中添加):

private class CustomeGestureDetector extends GestureDetector.SimpleOnGestureListener 
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) 
            if(e1 == null || e2 == null) return false;
            if(e1.getPointerCount() > 1 || e2.getPointerCount() > 1) return false;
            else 
                try 
                    if(e1.getY() - e2.getY() > 20 ) 
                            // Hide Actionbar
                        getSupportActionBar().hide();
                        customWebView.invalidate();
                       return false;
                    
                    else if (e2.getY() - e1.getY() > 20 ) 
                            // Show Actionbar
                        getSupportActionBar().show();
                        customWebView.invalidate();
                       return false;
                    

                 catch (Exception e) 
                    customWebView.invalidate();
                
                return false;
            


        
    

WebFragment.java

private CustomWebView customWebView;

customWebView= (CustomWebView) view.findViewById(R.id.customWebView);

customWebView.setGestureDetector(new GestureDetector(new CustomeGestureDetector()));

对我来说很好用,希望对你有帮助。

【讨论】:

谢谢你,这很有帮助!但是,我会将您的 CustomGestureDetector 类的名称更改为 CustomGestureDetectorListener 或其他名称,因为它不是 GestureDetector。事实上,它令人困惑。【参考方案3】:

package com.keshav.hideactionbarandfooterexample;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageButton;

import java.util.ArrayList;
import java.util.List;

import adapters.RecyclerAdapter;
import listners.HidingScrollListener;

public class MainActivity extends AppCompatActivity 

    private Toolbar mToolbar;
    private Toolbar toolbar_bottom;
    private ImageButton mFabButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        setTheme(R.style.AppThemeRed);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.e("keshav", "MainActivity called");

        initToolbar();
        mFabButton = (ImageButton) findViewById(R.id.fabButton);
        initRecyclerView();
    

    private void initToolbar() 
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar_bottom = (Toolbar) findViewById(R.id.toolbar_bottom);
        setSupportActionBar(mToolbar);
        setSupportActionBar(toolbar_bottom);
        setTitle(getString(R.string.app_name));
        mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
        toolbar_bottom.setTitleTextColor(getResources().getColor(android.R.color.white));


        toolbar_bottom.setVisibility(View.GONE);
    

    private void initRecyclerView() 
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
        recyclerView.setAdapter(recyclerAdapter);

        recyclerView.addOnScrollListener(new HidingScrollListener() 
            @Override
            public void onHide() 
                hideViews();
            

            @Override
            public void onShow() 
                showViews();
            
        );
    

    private void hideViews() 
        // TODO (-mToolbar)  plus means  2 view above ho jaye or not visible to user
        mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new AccelerateInterpolator(2));

        // TODO uncomment this Hide Footer in android when Scrolling
        // TODO (+mToolbar)  plus means  2 view forward ho jaye or not visible to user
        toolbar_bottom.animate().translationY(+toolbar_bottom.getHeight()).setInterpolator(new AccelerateInterpolator(2));

        // TODO keshav Hide Also Floatng Button In Android
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mFabButton.getLayoutParams();
        int fabBottomMargin = lp.bottomMargin;
        mFabButton.animate().translationY(mFabButton.getHeight() + fabBottomMargin).setInterpolator(new AccelerateInterpolator(2)).start();
        // TODO keshav Hide Also Floatng Button In Android
    

    private void showViews() 
        mToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));

        // TODO uncomment this Hide Footer in android when Scrolling
        toolbar_bottom.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
        mFabButton.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
    

    private List<String> createItemList() 
        List<String> itemList = new ArrayList<>();
        for (int i = 0; i < 20; i++) 
            itemList.add("Item " + i);
        
        return itemList;
    


=============================================
             RecyclerAdapter
=============================================
package adapters;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.keshav.hideactionbarandfooterexample.R;

import java.util.List;

/*
* RecyclerView Adapter that allows to add a header view.
* */
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> 

    private static final int TYPE_HEADER = 2;
    private static final int TYPE_ITEM = 1;
    private List<String> mItemList;

    public RecyclerAdapter(List<String> itemList) 
        mItemList = itemList;
    

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
        Context context = parent.getContext();
        if (viewType == TYPE_ITEM) 
            final View view = LayoutInflater.from(context).inflate(R.layout.recycler_item, parent, false);
            return RecyclerItemViewHolder.newInstance(view);
         else if (viewType == TYPE_HEADER) 
            final View view = LayoutInflater.from(context).inflate(R.layout.recycler_header, parent, false);
            return new RecyclerHeaderViewHolder(view);
        
        throw new RuntimeException("There is no type that matches the type " + viewType + " + make sure your using types correctly");
    

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) 
        if (!isPositionHeader(position)) 
            RecyclerItemViewHolder holder = (RecyclerItemViewHolder) viewHolder;
            String itemText = mItemList.get(position - 1); // header
            holder.setItemText(itemText);
        
    

    public int getBasicItemCount() 
        return mItemList == null ? 0 : mItemList.size();
    


    @Override
    public int getItemViewType(int position) 
        if (isPositionHeader(position)) 
            return TYPE_HEADER;
        

        return TYPE_ITEM;
    

    @Override
    public int getItemCount() 
        return getBasicItemCount() + 1; // header
    

    private boolean isPositionHeader(int position) 
        return position == 0;
    



=====================================================
         RecyclerHeaderViewHolder
=====================================================
package adapters;

import android.support.v7.widget.RecyclerView;
import android.view.View;

public class RecyclerHeaderViewHolder extends RecyclerView.ViewHolder 
    public RecyclerHeaderViewHolder(View itemView) 
        super(itemView);
    


=====================================================
              RecyclerItemViewHolder
=====================================================

package adapters;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;

import com.keshav.hideactionbarandfooterexample.R;


public class RecyclerItemViewHolder extends RecyclerView.ViewHolder 

    private final TextView mItemTextView;

    public RecyclerItemViewHolder(final View parent, TextView itemTextView) 
        super(parent);
        mItemTextView = itemTextView;
    

    public static RecyclerItemViewHolder newInstance(View parent) 
        TextView itemTextView = (TextView) parent.findViewById(R.id.itemTextView);
        return new RecyclerItemViewHolder(parent, itemTextView);
    

    public void setItemText(CharSequence text) 
        mItemTextView.setText(text);
    



===================================================
            activity_main.xml
===================================================

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_
                android:layout_>

    <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_
            android:layout_/>

    <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_
            android:layout_
            android:background="?attr/colorPrimary"/>

    <ImageButton
            android:id="@+id/fabButton"
            android:layout_
            android:layout_
            android:layout_gravity="bottom|right"
            android:layout_marginBottom="16dp"
            android:layout_marginRight="16dp"
            android:background="@drawable/fab_bcg"
            android:src="@drawable/ic_favorite_outline_white_24dp"
            android:contentDescription="@string/fab_description"/>


    <RelativeLayout
        android:layout_
        android:layout_>

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar_bottom"
        android:layout_
        android:layout_alignParentBottom="true"
        android:layout_
        android:background="?attr/colorPrimary"/>

    </RelativeLayout>

</FrameLayout>


==================================================
    recycle_header.xml in layout folder
==================================================

<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_
      android:layout_/>

==================================================
    recycle_item.xml in layout folder
==================================================
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_
    android:layout_
    android:layout_gravity="center"
    android:layout_margin="8dp"
    card_view:cardCornerRadius="4dp">
    <TextView
        android:id="@+id/itemTextView"
        android:layout_
        android:layout_
        android:gravity="center_vertical"
        android:padding="8dp"
        style="@style/Base.TextAppearance.AppCompat.Body2"/>
</android.support.v7.widget.CardView>


=================================================
                      styles.xml
=================================================
<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    </style>

    <style name="AppThemeRed" parent="AppTheme">
        <item name="colorPrimary">@color/color_primary_red</item>
        <item name="colorPrimaryDark">@color/color_primary_red_dark</item>
    </style>

    <style name="AppThemeGreen" parent="AppTheme">
        <item name="colorPrimary">@color/color_primary_green</item>
        <item name="colorPrimaryDark">@color/color_primary_green_dark</item>
    </style>

    <style name="AppThemeBlue" parent="AppTheme">
        <item name="colorPrimary">@color/color_primary_blue</item>
        <item name="colorPrimaryDark">@color/color_primary_blue_dark</item>
        <item name="colorAccent">@color/color_accent_pink</item>
    </style>

</resources>

build.gradle 依赖

  compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support:recyclerview-v7:25.3.1'
    compile 'com.android.support:cardview-v7:25.3.1'
    compile 'com.android.support:design:25.3.1'

【讨论】:

drive.google.com/open?id=0BzBKpZ4nzNzUVi0xeU1UMjZHeFE整个

以上是关于如何在 Webview 中向下滚动时隐藏操作栏/工具栏的主要内容,如果未能解决你的问题,请参考以下文章

如何在滚动时隐藏导航栏,除非在屏幕顶部

如何在 Xamarin Forms 中滚动时折叠(隐藏或向上滑动)导航栏(标题栏)?

向下滚动时隐藏导航栏并在用户使用 jquery 向上滚动页面时显示它,不能正常工作

没有滚动内容时如何下拉协调器布局

向下滚动时隐藏的 Flutter TabBar 和 SliverAppBar

向下滚动以逐渐隐藏菜单栏或视图并向上滚动