使用 ActionBar 的 Tablayout 的滚动行为无法正常工作
Posted
技术标签:
【中文标题】使用 ActionBar 的 Tablayout 的滚动行为无法正常工作【英文标题】:Scroll behaviour of Tablayout with ActionBar is not working properly 【发布时间】:2020-03-11 15:42:16 【问题描述】:我正在尝试实现类似 WhatsApp 的行为。
预期行为:
当用户滚动列表时,Tablayout
会随着操作栏向上滚动。
ActionBar
隐藏并安装 Tablayout
代替它。
发生了什么:
ActionBar
和 Tablayout
一切正常,但当向上滚动时,Tablayout
的位置被空白占据。
ScreenShot 1, ScreenShot 2
我正在尝试删除该空白但不能。
下面是我的Activity
和Fragment
代码
MainActivity.java
public class ViewPagerActivity extends AppCompatActivity
private TabLayout tabLayout;
private LockableViewPager viewPager;
private Toolbar toolbar;
private MaterialSearchView searchView;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager);
searchView = findViewById(R.id.search_view);
tabLayout = findViewById(R.id.tabs);
toolbar = findViewById(R.id.toolbar);
viewPager = findViewById(R.id.viewPager);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("WhatsApp");
toolbar.setTitleTextColor(Color.WHITE);
setupViewPager(viewPager);
tabLayout.setupWithViewPager(viewPager);
searchView.setOnSearchViewListener(new MaterialSearchView.SearchViewListener()
@Override
public void onSearchViewShown()
tabLayout.setVisibility(View.GONE);
TranslateAnimation animate = new TranslateAnimation(0, -tabLayout.getWidth(), 0, 0);
tabLayout.setAnimation(animate);
viewPager.setSwipeAble(false);
@Override
public void onSearchViewClosed()
tabLayout.setVisibility(View.VISIBLE);
TranslateAnimation animate = new TranslateAnimation(0, 0, 0, tabLayout.getHeight());
tabLayout.setAnimation(animate);
viewPager.setSwipeAble(true);
);
private void setupViewPager(ViewPager viewPager)
PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Tab1Fragment(), "CHATS");
adapter.addFragment(new Tab2Fragment(), "STATUS");
adapter.addFragment(new Tab2Fragment(), "CALLS");
viewPager.setAdapter(adapter);
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item)
switch (item.getItemId())
case android.R.id.home:
onBackPressed();
break;
return super.onOptionsItemSelected(item);
@Override
public void onBackPressed()
if (searchView.isSearchOpen())
searchView.closeSearch();
viewPager.setSwipeAble(true);
else
super.onBackPressed();
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_layout"
android:layout_
android:layout_
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/toolbar_container"
android:layout_
android:layout_
app:elevation="6dp">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_
android:layout_
android:layout_alignParentTop="true"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:elevation="0dp"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
</androidx.appcompat.widget.Toolbar>
<com.miguelcatalan.materialsearchview.MaterialSearchView
android:id="@+id/search_view"
android:layout_
android:layout_ />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_
android:layout_
android:layout_below="@+id/toolbar_container"
android:layout_marginTop="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:elevation="0dp"
app:tabIndicatorColor="#ffffff"
app:tabMode="fixed"
app:tabSelectedTextColor="#ffffff"
app:tabTextColor="#d3d3d3" />
</FrameLayout>
<com.example.fragmentcontroller.view_pager.LockableViewPager
android:id="@+id/viewPager"
android:layout_
android:layout_
android:layout_below="@+id/toolbar_container"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</RelativeLayout>
Tab1Fragment.java
public class Tab1Fragment extends Fragment implements View.OnClickListener
private float mToolbarHeight;
public Tab1Fragment()
// Required empty public constructor
private View view;
private MaterialSearchView searchView;
private ArrayList<ModelD> modelDArrayList;
private RecyclerView recyclerView;
private Toolbar toolbar;
private FrameLayout toolbarContainer;
private TabLayout tabs;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
view = inflater.inflate(R.layout.fragment_tab1, container, false);
return view;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
searchView = getActivity().findViewById(R.id.search_view);
toolbar = getActivity().findViewById(R.id.toolbar);
recyclerView = view.findViewById(R.id.recyclerView);
toolbarContainer = getActivity().findViewById(R.id.toolbar_container);
tabs = getActivity().findViewById(R.id.tabs);
mToolbarHeight = Utils.getToolbarHeight(getContext());
searchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener()
@Override
public boolean onQueryTextSubmit(String query)
return false;
@Override
public boolean onQueryTextChange(String newText)
if (newText.equals(""))
bindList(modelDArrayList);
else
ArrayList<ModelD> arrayList = new ArrayList<>();
for (int i = 0; i < modelDArrayList.size(); i++)
if
(modelDArrayList.get(i).getName().toLowerCase().contains((newText).toLowerCase()))
arrayList.add(modelDArrayList.get(i));
bindList(arrayList);
return false;
);
modelDArrayList = new ArrayList<>();
bindList(modelDArrayList);
recyclerView.setOnScrollListener(new HidingScrollListener(getContext())
@Override
public void onHide()
if (!searchView.isSearchOpen())
hideViews();
@Override
public void onMoved(int distance)
if (!searchView.isSearchOpen())
toolbarContainer.setTranslationY(-distance);
@Override
public void onShow()
showViews();
);
private void hideViews()
toolbar.animate().translationY(-toolbar.getHeight()).setInterpolator(new
AccelerateInterpolator(2));
// tabs.animate().translationY(-mToolbarHeight).setInterpolator(new
AccelerateInterpolator(2)).start();
private void showViews()
toolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
// tabs.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
private void bindList(ArrayList<ModelD> arrayList)
if (arrayList.isEmpty())
for (int i = 0; i < 20; i++)
ModelD modelD = new ModelD();
modelD.setName("Name " + i);
arrayList.add(modelD);
DAdapter adapter = new DAdapter(getContext(), arrayList);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter);
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
inflater.inflate(R.menu.menu_search, menu);
MenuItem item = menu.findItem(R.id.action_search);
if (searchView != null)
searchView.setMenuItem(item);
super.onCreateOptionsMenu(menu, inflater);
@Override
public void onClick(View v)
tab1_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
tools:context=".view_pager.fragments.Tab1Fragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_
android:layout_ />
</FrameLayout>
【问题讨论】:
请在您的 xml 文件中在 Toolbar 之前使用 AppBarLayout。 【参考方案1】:你应该使用CoordinatorLayout
您使用的app:layout_scrollFlags="scroll|enterAlways|snap"
、app:layout_behavior="@string/appbar_scrolling_view_behavior"
仅适用于 CoordinatorLayout。
正确的实现如下所示。
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_layout"
android:layout_
android:layout_>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/toolbar_container"
android:layout_
android:layout_>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_
android:layout_
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:elevation="0dp"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
</androidx.appcompat.widget.Toolbar>
<com.miguelcatalan.materialsearchview.MaterialSearchView
android:id="@+id/search_view"
android:layout_
android:layout_
app:layout_scrollFlags="scroll|enterAlways|snap" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_
android:layout_
android:layout_marginTop="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:elevation="0dp"
app:tabIndicatorColor="#ffffff"
app:tabMode="fixed"
app:layout_scrollFlags="noScroll"
app:tabSelectedTextColor="#ffffff"
app:tabTextColor="#d3d3d3" />
</com.google.android.material.appbar.AppBarLayout>
<com.example.fragmentcontroller.view_pager.LockableViewPager
android:id="@+id/viewPager"
android:layout_
android:layout_
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
如果您需要更详细的说明,请查看link。
【讨论】:
以上是关于使用 ActionBar 的 Tablayout 的滚动行为无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章
是否可以强制 TabLayout 根据 TabLayout.Tab 文本长度使用动态 TabLayout.Tab 宽度?
使用Tablayout出现标题消失的原因:setupWithViewPager()的大坑