带 ActionBar 的 Tablayout 的滚动行为无法正常工作
Scroll behaviour of Tablayout with ActionBar is not working properly
我正在尝试实现类似 whatsApp 的行为。
预期行为:
当用户滚动列表时 Tablayout
使用操作栏向上滚动。
ActionBar
隐藏并取而代之 Tablayout
取而代之。
发生了什么:
ActionBar
和 Tablayout
一切正常,但是当向上滚动时 Tablayout
的位置被白色 space.
占据
ScreenShot 1, ScreenShot 2
我正试图移除那个白色 space 但没成功。
下面是我的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_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/toolbar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="6dp">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="wrap_content" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dp"
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_width="match_parent"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="match_parent"
tools:context=".view_pager.fragments.Tab1Fragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
你应该使用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_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/toolbar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways|snap" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dp"
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_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
如果您需要更详细的解释,请查看此 link。
我正在尝试实现类似 whatsApp 的行为。
预期行为:
当用户滚动列表时 Tablayout
使用操作栏向上滚动。
ActionBar
隐藏并取而代之 Tablayout
取而代之。
发生了什么:
ActionBar
和 Tablayout
一切正常,但是当向上滚动时 Tablayout
的位置被白色 space.
ScreenShot 1, ScreenShot 2
我正试图移除那个白色 space 但没成功。
下面是我的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_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/toolbar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="6dp">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="wrap_content" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dp"
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_width="match_parent"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="match_parent"
tools:context=".view_pager.fragments.Tab1Fragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
你应该使用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_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/toolbar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways|snap" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dp"
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_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
如果您需要更详细的解释,请查看此 link。