【Android】I can’t describe this effect

【Android】I can’t describe this effect

Preface

I recently received a request that made me feel embarrassed. (Here are some nonsense words)

The required effect is like this, there is a floating part at the top, followed by some layouts, and several switchable Tab pages below, and then when you scroll~~blah blah blah blah~~ Let's just look at the picture directly

The main thing is the suspension of the top and Tab, and the effect of being pushed down.

[[209268]]

When I heard that this effect could be achieved, the kitchen knife in my drawer that I used to chop produce started to stir.

Ideas

Let's talk about the idea of ​​implementation first. The above effect can be roughly divided into two parts:

1. Tab is suspended when scrolling up to the top

The Tab will float at the top after scrolling~~ This effect can be easily achieved using CoordinatorLayout + AppBarLayout. (What? You still don’t know how to use these two controls? Well, you should be able to barely understand the following content)

2. Top suspension and the effect of being pushed away

Just wrap a layer of FrameLayout outside the CoordinatorLayout, and then change the top layout to the top. Then monitor the scrolling of AppBarLayout and use topMargin to achieve the effect of being "pushed up"

The split is complete, the next step is to realize

accomplish

  • Tab suspension effect

Use CoordinatorLayout, AppBarLayout, TabLayout, and ViewPager to achieve the floating effect of Tab

  1. <br>

Set app:layout_scrollFlags="scroll|exitUntilCollapsed" in LinearLayout, but do not set app:layout_scrollFlags attribute in TabLayout

Use app:layout_behavior="@string/appbar_scrolling_view_behavior" in ViewPager

layout_scrollFlags: AppBarLayout attributes for Children View, with five values: scroll, enterAlways, enterAlwaysCollapsed, snap, exitUntilCollapsed. For specific usage, please refer to Android Detailed Analysis of AppBarLayout's Five ScrollFlags

(I won’t go into details about the usage of CoordinatorLayout and AppBarLayout)

Then, just add a few list fragments to ViewPager in the Java code to see the following effect (Note: the list cannot be ListView, you need to use RecyclerView)

So far, most of the effects have been achieved. The final value just needs to achieve the effect of being pushed away.

  • The effect of the top being "pushed away"

At this time, the layout changes slightly.

  1. <br>

On the basis of the original, a FrameLayout is set, and the floating part at the top can be realized by FrameLayout. This also causes the layout below to be partially covered, so an empty View with the same height as the floating part is added to the LinearLayout.

The layout is completed, but how to achieve the "pushed away" effect? ​​At this time, just listen to the scrolling of AppBarLayout in MainActivity.

  1. @BindView(R.id.app_bar)
  2. AppBarLayout mAppBar;
  3. @BindView(R.id.sticky_view)
  4. View mStickyView;
  5. @BindView(R.id.header)
  6. View mHeader;
  7. private void setAppBarListener() {
  8. mAppBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
  9. @Override
  10. public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
  11. //Head height (excluding the part covered by the top)
  12. int minScrollHeight = mHeader.getMeasuredHeight();
  13. int margin = minScrollHeight + verticalOffset;
  14. margin = margin > 0 ? 0 : margin;
  15. FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mStickyView.getLayoutParams();
  16. layoutParams.topMargin = margin;
  17. mStickyView.setLayoutParams(layoutParams);
  18. }
  19. });
  20. }

Here, the margin value is calculated by monitoring the scrolling of AppBarLayout (when scrolling up, the verticalOffset value changes to: 0, -1, -2... -n-1, -n). By changing the topMargin, the "pushing away" effect is achieved.

Take another look at the effect:

Having reached this point, I quietly put away the kitchen knife I used to chop produce.

Tips

Problem: Scrolling is not smooth when using CoordinatorLayout

Solution: You can write a Behavior and add it to AppBarLayout. Specific solution

Problem: If you want to refresh the page, and you put a SwipeRefreshLayout outside of CoordinatorLayout, you may accidentally trigger a refresh~~ (experience it yourself)

Solution: This problem can be solved by monitoring AppBarLayout and setting swipeLayout to Enabled.

  1. mAblAppBar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
  2. if (verticalOffset == 0) {
  3. swipeLayout.setEnabled( true );
  4. } else {
  5. if (!swipeLayout.isRefreshing()) {
  6. swipeLayout.setEnabled( false );
  7. }
  8. }
  9. });

<<:  Android solves ListView loading picture flickering

>>:  The fourth issue of the Aiti Tribe live class: How to quickly convert an H5 website into an App?

Recommend

Double 11 is coming, how can e-commerce platforms win the "volume war"?

This year marks the tenth year of " Double E...

5 great file managers for Android TV

[51CTO.com Quick Translation] Android TV is a TV ...

iOS 12.4.1 released, may fix jailbreak vulnerability

Apple recently released the official version of i...

Interpretation of Meituan’s latest advertisement

How to make advertisements more attractive and le...

Yu Sheng: Number portability from a software design perspective

[[256813]] The issue of "number portability&...

Interview experience: WeChat, NetEase Games, Jinshan Xishanju, Renren

[[144779]] WeChat Interview Experience Backend de...

Baidu search for 18 details of ocpc (Part 2)

Continuing from the previous article "18 det...