滚动选项卡中的片段时隐藏/显示工具栏
Posted
技术标签:
【中文标题】滚动选项卡中的片段时隐藏/显示工具栏【英文标题】:Hiding/Showing the toolbar when fragment in the tabs is scrolled 【发布时间】:2015-11-11 05:16:05 【问题描述】:我在我的安卓应用中添加了新的Toolbar
、Tablayout
和Viewpager
。我为我的 3 个选项卡提供了 Fragments,并且工作正常。但问题是,当我向上滚动时,我的工具栏并没有隐藏。我希望当我滚动我的片段时它应该隐藏。还有一件事,我在片段中使用 Webview。
我的代码如下。
MainActivity.Java
public class MainActivity extends AppCompatActivity
TabLayout tabLayout;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setupToolbar();
setupTablayout();
private void setupToolbar()
// TODO Auto-generated method stub
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbarsdfs);
if (toolbar != null)
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
private void setupTablayout()
// TODO Auto-generated method stub
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new PagerAdapter
(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
@Override
public void onTabSelected(TabLayout.Tab tab)
viewPager.setCurrentItem(tab.getPosition());
@Override
public void onTabUnselected(TabLayout.Tab tab)
@Override
public void onTabReselected(TabLayout.Tab tab)
);
main.xml
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinatorLayout"
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/toolbarsdfs"
android:layout_
android:layout_
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimaryDark"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:layout_scrollFlags="scroll|enterAlways"/>
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:scrollbars="horizontal"
android:layout_below="@+id/toolbar"
android:layout_
android:layout_
android:background="?attr/colorPrimary" />
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_
android:layout_
android:layout_below="@+id/tablayout"/>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
PagerAdapter.Java
public class PagerAdapter extends FragmentStatePagerAdapter
int mNumOfTabs;
public PagerAdapter(FragmentManager fm, int NumOfTabs)
super(fm);
this.mNumOfTabs = NumOfTabs;
@Override
public Fragment getItem(int position)
switch (position)
case 0:
Fragment_Feeds tab1 = new Fragment_Feeds();
return tab1;
case 1:
Fragment_Facts tab2 = new Fragment_Facts();
return tab2;
default:
return null;
@Override
public int getCount()
return mNumOfTabs;
Fragment_Feeds.java
public class Fragment_Feeds extends Fragment
SwipeRefreshLayout swipeView;
WebView myWebView;
ProgressBar progressBar;
final static String myBlogAddr = "http://myblog.com";
String myUrl;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
View view = inflater.inflate(R.layout.fragmentfeeds, container, false);
swipeView = (SwipeRefreshLayout) view.findViewById(R.id.swipe);
myWebView = (WebView) view.findViewById(R.id.webview);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
myWebView.setWebViewClient(new MyWebViewClient());
WebSettings webSettings = myWebView.getSettings();
webSettings.setjavascriptEnabled(true);
myWebView.setOverScrollMode(View.OVER_SCROLL_NEVER);
myWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
myWebView.setHorizontalScrollBarEnabled(false);
myWebView.loadUrl("http://myblog.com");
swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
@Override
public void onRefresh()
myWebView.loadUrl("http://myblog.com");
);
return view;
private class MyWebViewClient extends WebViewClient
@Override
public void onPageFinished(WebView view, String url)
swipeView.setRefreshing(false);
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
myUrl = url;
view.loadUrl(url);
return true;
@Override
public void onReceivedError(WebView view, int errorCod,String description, String failingUrl)
myWebView.loadUrl("file:///android_asset/error_page.html");
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
inflater.inflate(R.menu.main, menu);
super.onCreateOptionsMenu(menu, inflater);
fragmentfeeds.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical"
android:background="#FFFFFF" >
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleSmall"
android:layout_
android:layout_ />
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe"
android:layout_
android:layout_
android:background="#FFFFFF">s
<WebView
android:id="@+id/webview"
android:layout_
android:layout_
android:numColumns="1"
android:scrollbars="none"
android:focusableInTouchMode="false"
android:focusable="false"
android:background="#FFFFFF" />
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
我想要什么?
我想要的是,当我向上滚动 webview 时,工具栏也应该向上滚动并隐藏,当我向下滚动时,工具栏应该尽快返回。
【问题讨论】:
Check This Sample 在工具栏中添加 app:layout_scrollFlags="scroll|enterAlways" 如果你在片段中使用gridview,那么在gridview中添加android:nestedScrollingEnabled="true" 【参考方案1】:试试这个。
main.xml
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinatorLayout"
android:layout_
android:layout_
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_
android:layout_
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbarsdfs"
android:layout_
android:layout_
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"/>
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:scrollbars="horizontal"
android:layout_below="@+id/toolbarsdfs"
android:layout_
android:layout_
android:background="?attr/colorPrimary"
app:tabTextColor="@android:color/white"
app:tabSelectedTextColor="@android:color/white"
app:tabIndicatorColor="@android:color/white"
app:tabIndicatorHeight="3dp" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_
android:layout_
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_below="@+id/tablayout"/>
</android.support.design.widget.CoordinatorLayout>
fragmentfeeds.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:isScrollContainer="false"
android:layout_
android:layout_
android:layout_gravity="fill_vertical"
android:clipToPadding="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_
android:layout_
android:orientation="vertical">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleSmall"
android:layout_
android:layout_ />
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe"
android:layout_
android:layout_
android:background="#FFFFFF">
<WebView
android:id="@+id/webviewtool"
android:layout_
android:layout_
android:numColumns="1"
android:focusableInTouchMode="false"
android:focusable="false"
android:background="#FFFFFF" />
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
【讨论】:
【参考方案2】:首先,您应该将您的 webview 移动到 NestedScrollView 并将 'android:isScrollContainer' 属性设置为 'false' 值。 https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html
其次,您应该将 ViewPager 移到 AppBarLayout 之外。 所以,你的 main.xml 应该是这样的:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:background="#FFF"
android:clickable="true"
android:layout_
android:layout_>
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_
android:layout_
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<!-- your app bar stuff here -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
app:layout_scrollFlags="scroll|enterAlways">
<ImageView
android:layout_
android:layout_
android:scaleType="fitXY"
android:id="@+id/image_header"/>
<include layout="@layout/header"/>
</FrameLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:background="#FFF"
app:tabTextColor="#a3a3a3"
app:tabSelectedTextColor="#a3a3a3"
app:tabIndicatorColor="#0042ab"
android:layout_
android:layout_
/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_
android:layout_
android:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:background="#eaeaea"/>
AppBarLayout 子节点只有在有标志 app:layout_scrollFlags 时才会隐藏
在此处阅读有关实施支持设计库的更多信息:https://android-developers.googleblog.com/2015/05/android-design-support-library.html
【讨论】:
我不能使用您应该将 ViewPager 移到 AppBarLayout 之外,并将行为添加到 ViewPager app:layout_behavior="@string/appbar_scrolling_view_behavior"
我写了一个完整的例子! https://github.com/erikcaffrey/AndroidDesignSupportLibrary
希望对你有帮助!
【讨论】:
【参考方案4】:看看
How to properly hide&show the actionbar using the new design library API? Android-ObservableScrollView【讨论】:
【参考方案5】:对不起我的英语。
我将向您展示我是如何为我的应用程序制作的(最小 sdk:14,目标 sdk:22)。我不使用片段,我的活动中只有一个 webview,但处理程序是相同的。问题是当您在 webview 中滚动时,Android 不会像滚动事件那样处理它,webview 会处理自己的事件。
首先我在 res 文件夹中定义了 styles.xml。我使用透明且叠加的 ActionBar,当您想要隐藏和显示时效果会更好:
res/styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="@android:style/Theme.Holo">
<!-- Customize your theme here. -->
<item name="android:windowActionBarOverlay">true</item>
<item name="android:actionBarStyle">@style/MyActionBar</item>
</style>
<!-- ACTION BAR STYLES -->
<style name="MyActionBar" parent="@android:style/Widget.Holo.ActionBar">
<item name="android:background">@color/actionbar_background</item>
</style>
</resources>
然后在清单中,我在应用程序部分定义应用程序和 ActionBar 的样式:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
最后在MainActivity中,你必须控制webview中的手势。您必须实现 View.OnTouchListener 和 Handler.Callback。当你触摸 webview 时,你必须比较 start 事件和 end 事件:
MainActivity.Java
public class MainActivity extends Activity implements View.OnTouchListener, Handler.Callback
private float x1,x2,y1,y2; //x1, y1 is the start of the event, x2, y2 is the end.
static final int MIN_DISTANCE = 150; //min distance for a scroll up event
private static final int CLICK_ON_WEBVIEW = 1;
private static final int CLICK_ON_URL = 2;
private static final int UP_ON_WEBVIEW = 3;
private final Handler handler = new Handler(this);
public WebView webView;
private WebViewClient client;
private WebAppInterface webAppInt = new WebAppInterface(this);
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView)findViewById(R.id.myWebView);
webView.setOnTouchListener(this);
client = new WebViewClient();
webView.setWebViewClient(client);
webView.loadDataWithBaseURL("file:///android_asset/", "myweb.html", "text/html", "UTF-8", "");
//HERE START THE IMPORTANT PART
@Override
public boolean onTouch(View v, MotionEvent event)
if (v.getId() == R.id.myWebView && event.getAction() == MotionEvent.ACTION_DOWN)
x1 = event.getX();
y1 = event.getY();
handler.sendEmptyMessageDelayed(CLICK_ON_WEBVIEW, 200);
else if (v.getId() == R.id.myWebView && event.getAction() == MotionEvent.ACTION_UP)
x2 = event.getX();
y2 = event.getY();
handler.sendEmptyMessageDelayed(UP_ON_WEBVIEW, 200);
return false;
@Override
public boolean handleMessage(Message msg)
if (msg.what == CLICK_ON_URL) //if you clic a link in the webview, thats not a scroll
handler.removeMessages(CLICK_ON_WEBVIEW);
handler.removeMessages(UP_ON_WEBVIEW);
return true;
if (msg.what == CLICK_ON_WEBVIEW)
Toast.makeText(this, "WebView clicked", Toast.LENGTH_SHORT).show();
return true;
if (msg.what == UP_ON_WEBVIEW)
float deltaX = x2 - x1; //horizontal move distance
float deltaY = y2 - y1; //vertical move distance
if ((Math.abs(deltaX) > MIN_DISTANCE) && (Math.abs(deltaX) > Math.abs(deltaY)))
// Left to Right swipe action
if (x2 > x1)
Toast.makeText(this, "Left to Right swipe [Next]", Toast.LENGTH_SHORT).show ();
// Right to left swipe action
else
Toast.makeText(this, "Right to Left swipe [Previous]", Toast.LENGTH_SHORT).show ();
else if ((Math.abs(deltaY) > MIN_DISTANCE) && (Math.abs(deltaY) > Math.abs(deltaX)))
// Top to Bottom swipe action -- i SWOW MY ACTIONBAR ON SCROLLDOWN
if (y2 > y1)
getActionBar().show();
Toast.makeText(this, "Top to Bottom swipe [Show Bar]", Toast.LENGTH_SHORT).show ();
// Bottom to top swipe action -- I HIDE MY ACTIONBAR ON SCROLLUP
else
getActionBar().hide();
Toast.makeText(this, "Bottom to Top swipe [Hide Bar]", Toast.LENGTH_SHORT).show ();
return true;
return false;
希望对你有帮助。
【讨论】:
【参考方案6】:隐藏特定片段的菜单:
setHasOptionsMenu(true); //Inside of onCreate in FRAGMENT:
@Override
public void onPrepareOptionsMenu(Menu menu)
menu.findItem(R.id.action_search).setVisible(false);
【讨论】:
【参考方案7】:只需将此行添加到您的工具栏或 FAB 按钮中即可。
app:layout_scrollFlags="scroll|enterAlways"
app:layout_scrollFlags="scroll|enterAlways"
行将导致我们的Toolbar
将在用户向下滚动列表时滚动屏幕,而一旦他开始向上滚动,Toolbar
将再次出现。干净简洁,这就是CoordinatorLayout
的力量!
请查看此链接 https://mzgreen.github.io/2015/06/23/How-to-hideshow-Toolbar-when-list-is-scrolling(part3)/&re=1&ts=1453224208&sig=ALL1Aj5aKrtAlylt-Qt3Ci6uwff76BqQYw
【讨论】:
【参考方案8】:只需将app:layout_scrollFlags="scroll|enterAlways"
放在您的工具栏上就足够了。
【讨论】:
以上是关于滚动选项卡中的片段时隐藏/显示工具栏的主要内容,如果未能解决你的问题,请参考以下文章