Top TabLayout with Dynamic Height ViewPager Effect

First look at the effect picture (gif recording is a bit of a problem...Take a look at it: ...

First look at the effect picture (gif recording is a bit of a problem...Take a look at it:

Ideas:
1. Dynamic Height ViewPager with TabLayout
2. Let Header's TabLayout show or hide when sliding according to the sliding position
3. After sliding, let ScrollView slide to the specified position (ViewPager layout position) according to the current sliding position

Home page layout code:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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="com.example.v_xuyan.androidtest.TabLayoutActivity"> <ScrollView android:id="@+id/main_scroller" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <!--Simulate data on the main display entry--> <View android:background="#00FF00" android:layout_width="match_parent" android:layout_height="70dp"/> <FrameLayout android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> </ScrollView> <!--Slide Over Main Layout TabLayout After passing this TabLayout display--> <com.example.v_xuyan.androidtest.view.WrapWidthTabLayout android:id="@+id/main_tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFFFFFFF" android:visibility="gone" tools:visibility="visible"/> </RelativeLayout>

ContentFragment Main Layout Code

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" xmlns:app="http://schemas.android.com/apk/res-auto"> <!--Our main presentation item is the overall layout--> <!--simulation TabLayout With the data above, change the height yourself to simulate different data effects--> <View android:id="@+id/head_view" android:layout_width="match_parent" android:layout_height="20dp" android:background="@color/colorAccent"/> <!--with TabLayout--> <com.example.v_xuyan.androidtest.view.WrapWidthTabLayout android:id="@+id/tab_indicator" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabIndicatorHeight="2dp" app:tabIndicatorColor="@color/colorPrimary"/> <!--Dynamically changing height ViewPager--> <com.example.v_xuyan.androidtest.view.DynamicHeightViewPager android:id="@+id/content_view_pager" android:layout_width="match_parent" android:layout_height="match_parent"/> <!--For the sake of ScrollView Height that can be set by scrolling--> <View android:background="@color/colorPrimary" android:layout_width="match_parent" android:layout_height="900dp"/> </LinearLayout>

Main page uses ContentFragment layout

public class TabLayoutActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_tab_layout); getSupportFragmentManager().beginTransaction() .replace(R.id.main_content,new ContentFragment()).commit(); } }

ContentFragment code:

public class ContentFragment extends Fragment { private View mRootView; private TabLayout mTabLayout; private DynamicHeightViewPager mViewPager; private List<MyContentFragment> mFragments; private List<String> mTitles; private TabAdapter mAdapter; private View mHeader; private TabLayout mTabHeader; private ScrollView mScrollView; private boolean isHeaderShow; private int mHeaderTop;//Distance from top of main layout TabLayout content int toTopDistance = 0;//Distance from top of main layout @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { mRootView = inflater.inflate(R.layout.content_item, container, false); mTabLayout = mRootView.findViewById(R.id.tab_indicator); mViewPager = mRootView.findViewById(R.id.content_view_pager); mHeader = mRootView.findViewById(R.id.head_view); initData(); mAdapter = new TabAdapter(getChildFragmentManager()); mViewPager.setAdapter(mAdapter); mTabLayout.setupWithViewPager(mViewPager); //Add page switching monitoring to dynamically change the height of the ViewPager and top our main layout //to measure height realize dynamic height mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { super.onPageSelected(position); if (position > mAdapter.getCount() || mViewPager == null || mHeader == null) return; int num;//Simulate the height of the content area of the main layout TabLayout if (position == 0) { num = 50; } else { num = 20; } MyContentFragment fragment = (MyContentFragment) mAdapter.getItem(position); mViewPager.measuredCurrentView(fragment.getContainer());//Pass rootView to ViewPager to measure height ViewGroup.LayoutParams params = mHeader.getLayoutParams(); params.height = (int) ViewUtils.dp2px(getActivity(), num); mHeader.setLayoutParams(params); // to scroll top let the ContentFragment's View //Slide ViewPager to top the main layout int distance = mHeaderTop - mScrollView.getScrollY(); mScrollView.scrollBy(0,distance); //if ContentFragment's View is in the top then //Start with the main layout directly, without the content area above it, so scroll directly to the initial position //mScrollView.fullScroll(View.FOCUS_UP); } }); //coordinate the onPageSelected,the first show time is called //Combined with ViewPager Page Slide Monitor, Page Slide Monitor does not trigger when first displayed, which is executed when Page Layout is complete mViewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { MyContentFragment fragment = (MyContentFragment) mAdapter.getItem(0); if (mViewPager != null && fragment != null && mHeader != null) { mViewPager.measuredCurrentView(fragment.getContainer()); ViewGroup.LayoutParams params = mHeader.getLayoutParams(); params.height = (int) ViewUtils.dp2px(getActivity(), 50); mHeader.setLayoutParams(params);//Set the height of the layout on the main layout TabLayout to simulate the size of the data area } if (mViewPager != null && mViewPager.getViewTreeObserver() != null) { mViewPager.getViewTreeObserver().removeOnGlobalLayoutListener(this);//Remove, then use Slide Listening to implement } } }); setupTabHeader(); return mRootView; } private void setupTabHeader() { if (getActivity() != null && !getActivity().isFinishing()) { mTabHeader = getActivity().findViewById(R.id.main_tab_layout); if (mTabHeader != null && mViewPager != null) { mTabHeader.setupWithViewPager(mViewPager); } mScrollView = getActivity().findViewById(R.id.main_scroller); if (mScrollView != null) { mScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { //ScrollView's scroll listens for events and sliding distances to control whether the main page TabLayout layout is displayed updateHeaderView(); } }); } } } // onScrollChange is before onCreateView //Set whether the TabLayout on the home page is visible private void updateHeaderView() { getTopDistance(); int start = toTopDistance + mTabLayout.getTop(); int end = toTopDistance + mViewPager.getBottom() - mTabHeader.getMeasuredHeight();//to dismiss | subtract mTabHeader's Height if (mScrollView.getScrollY() > start && mScrollView.getScrollY() < end) { mTabHeader.setVisibility(View.VISIBLE); isHeaderShow = true; } if (mScrollView.getScrollY() > end || mScrollView.getScrollY() < start) { mTabHeader.setVisibility(View.GONE); isHeaderShow = false; } } //We get the distance from the top private void getTopDistance() { //to get mRootView top if (getActivity() != null && !getActivity().isFinishing()) toTopDistance = getActivity().findViewById(R.id.main_content).getTop(); mHeaderTop = toTopDistance + mHeader.getTop(); } private void initData() { mTitles = new ArrayList<>(); mTitles.add("Jie Feng Dyng"); mTitles.add("Living lotus"); mFragments = new ArrayList<>(); MyContentFragment fragment1 = new MyContentFragment(); Bundle bundle1 = new Bundle(); bundle1.putInt("num", 1); fragment1.setArguments(bundle1); mFragments.add(fragment1); MyContentFragment fragment2 = new MyContentFragment(); Bundle bundle2 = new Bundle(); bundle2.putInt("num", 2); fragment2.setArguments(bundle2); mFragments.add(fragment2); } class TabAdapter extends FragmentPagerAdapter { TabAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return mFragments.get(position); } @Override public int getCount() { return mFragments.size(); } @Nullable @Override public CharSequence getPageTitle(int position) { return mTitles.get(position); } } }

Finally, the layout and code for MyContentFragment:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.RecyclerView android:id="@+id/item_content_list" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> item layout <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/inner_item_text" android:textSize="15sp" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
public class MyContentFragment extends Fragment { private ViewGroup mContainer; private List<String> mList; private RecyclerView itemList; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.content_item_inner,container,false); mContainer = (ViewGroup) view; itemList = view.findViewById(R.id.item_content_list); initData(); itemList.setLayoutManager(new LinearLayoutManager(getActivity())); itemList.setAdapter(new MyAdapter()); return view; } private void initData() { Bundle mBundle = getArguments(); mList = new ArrayList<>(); if (mBundle == null) return; int num = mBundle.getInt("num"); switch (num) { case 1: for (int i = 0; i < 5; i++) { mList.add("Drunkuff " + i); } break; case 2: for (int i = 0; i < 10; i++) { mList.add("Fold Willow Ramadan " + i); } break; } } //Get rootView passed to ViewPager to measure height public ViewGroup getContainer(){ return mContainer; } class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{ @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(getActivity()).inflate(R.layout.inner_item_content, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(MyAdapter.ViewHolder holder, int position) { holder.item.setText(mList.get(position)); } @Override public int getItemCount() { return mList.size(); } class ViewHolder extends RecyclerView.ViewHolder{ private TextView item; ViewHolder(View itemView) { super(itemView); item = itemView.findViewById(R.id.inner_item_text); } } } }

A hole in the middle is the ViewPager layout in ScrollView.
If onMeasure is not overridden by a fixed height or custom ViewPager,
ViewPager height is 0, related to the internal mechanism of ScrollView, time to study

Attach a link to the project: github project address

In the future, keep writing as much as you can every weekend.Dao You supervise Ha!

12 May 2020, 12:24 | Views: 10022

Add new comment

For adding a comment, please log in
or create account

0 comments