Android custom View: Customizable top-level ScrollView, View sliding Principle Analysis, androidscrollview
When using various apps, I found a feature. The current App basically adds a pin button to the top of the page that can be swiped, so that users can easily return to the top, just like almost all pages on a webpage have buttons with top effects, I think this interaction is good and will certainly be used in my own projects in the future, I took the time to implement this small function. Now I will record the implementation process to facilitate future use.
Let's take a look at it first:
When ScrollView slides up more than a certain distance, a top button will appear in the gradient. When the sliding distance is smaller than the distance we specify, the button will disappear in a gradient way.
Implementation principle:
The implementation principle of this small case is very simple: 1. Listen to the onScrollChanged () method of the View and obtain the sliding distance of ScrolView. If the distance is greater than ours, a pin button is displayed. Otherwise, the screen is hidden.
2. Click the event processing button and click the button to move the entire ScrollView to the (0, 0) position.
Although this case is very simple, it involves the sliding principle of android. The onScrollViewChanged method belongs to the View class. It can also be seen that any View of android can be slide. In this case, I will explain my understanding of the android sliding principle.
Custom ScrollView code:
<Span style = "font-size: 14px; "> /************************************* * ********************** @ File Name: goTopScrollView. java * @ file Author: rzq * @ file Description: After sliding beyond a certain distance, the top button * @ modify history appears: create the initial version ************************************** on April 9, March 26, 2015 ************************************ * *******************/public class GoTopScrollView extends ScrollView implements OnClickListener {private ImageView goTopBtn; private int screenHeight; public GoTopScrollView (Context context, AttributeSet attrs) {super (context, attrs);} public void setScrollListener (ImageView goTopBtn) {this. goTopBtn = goTopBtn; this. goTopBtn. setOnClickListener (this) ;}@ Overrideprotected void onScrollChanged (int l, int t, int oldl, int oldt) {super. onScrollChanged (l, t, oldl, oldt);/*** the sliding distance exceeds 300 PX, And the up button appears, which can be used as a custom property */if (t> =) {goTopBtn. setVisibility (View. VISIBLE);} else {goTopBtn. setVisibility (View. GONE) ;}@ Overridepublic void onClick (View v) {if (v. getId () = R. id. go_top_btn) {this. smoothScrollTo (0, 0) ;}}</span>
Activity Code:
<span style="font-size:14px;">private void initView(){container = (RelativeLayout) findViewById(R.id.container);container.setLayoutTransition(new LayoutTransition());goTopBtn = (ImageView) findViewById(R.id.go_top_btn);scrollView = (GoTopScrollView) findViewById(R.id.scroll_view);scrollView.setScrollListener(goTopBtn);}</span>
This makes it easy to implement the top-level effect, but this is not enough. Now let's analyze what the android sliding principle is and whether it is only ScrollView that can slide.
1. First, any View in android can be slide. Why? Please refer to the key source code in the View and pick out only the Code related to the slide:
<Span style = "font-size: 14px;">/*** specifies the sliding of the X axis, Y axis does not move * @ param value the x position to scroll to */public void setScrollX (int value) {scrollTo (value, mScrollY);}/*** specifies the slide of the Y axis, X axis does not move * @ param value the y position to scroll to */public void setScrollY (int value) {scrollTo (mScrollX, value );} /*** Method for actually processing slide * @ param x the x position to scroll to * @ param y the y position to scroll to */public void s CrollTo (int x, int y) {if (mScrollX! = X | mScrollY! = Y) {int oldX = mScrollX; int oldY = mScrollY; mScrollX = x; mScrollY = y; invalidateParentCaches (); onScrollChanged (mScrollX, mScrollY, oldX, oldY); if (! AwakenScrollBars () {postInvalidateOnAnimation () ;}}/ *** Move the scrolled position of your view. this will cause a call to * {@ link # onScrollChanged (int, int)} and the view will be * invalidated. * @ param x the amount of pixels to scroll by horizontally * @ param y the amount of pixels to scroll by vertically */public void scrollBy (int x, int y) {scrollTo (mScrollX + x, mScrollY + Y);}/*** the listener that triggers the sliding * @ param l Current horizontal scroll origin. * @ param t Current vertical scroll origin. * @ param oldl Previous horizontal scroll origin. * @ param oldt Previous vertical scroll origin. */protected void onScrollChanged (int l, int t, int oldl, int oldt) {if (AccessibilityManager. getInstance (mContext ). isEnabled () {postSendViewScrolledAccessibilityEventCallback ();} mBackground SizeChanged = true; final AttachInfo ai = mAttachInfo; if (ai! = Null) {ai. mViewScrollChanged = true ;}</span> <span style = "font-size: 14px;"> </span>
From these methods, we can see that all views in android can be slide. In fact, all views have two sets of coordinate systems. One is the X, Y, the other pair specifies the View sliding coordinate system, mScrollX and mScrollY. The two pairs of coordinate systems are completely independent, that is, the changes in the X and Y coordinates do not affect the mScrollX and mScrollY, and vice versa. Next, we will focus on the scrollTo method.
ScrollTo (int x, int y) isContentSlide to the corresponding position, The reference coordinate system origin is the upper left corner of the parent View.
Call scrollTo (100, 0) to move the content in the View to the position x = 100, y = 0, as shown in. Note: The area of the yellow rectangle in the figure indicates a parent View, and the green dotted rectangle indicates the content in the parent view. In general, the sizes of the two are the same. This article draws a smaller dotted line box for ease of display. The position of the yellow area in the figure remains unchanged, and the position changes with the displayed content ,:
MScrollX and mScrollY are variables used to record sliding positions in the View class. These two functions finally call the onScrollChanged () function.
To sum up, the sliding principle of android is to change the sliding Coordinate System of the View by calling scrollTo () and save it in the member variables of mScrollX and mScrollY, we can get the sliding coordinate value through getScrollX () and getScrollY.
From the figure, we can see that when we call scrollTo (, 0);, we find that the View slides to the left, and the incoming positive number slides to the left, this is the opposite of what we usually understand. In fact, it is not in conflict, because the sliding coordinate system is different from our normal coordinate system. By calling the scrollTo method, the following code will be executed:
public void invalidate(int l, int t, int r, int b) { if (ViewDebug.TRACE_HIERARCHY) { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); } if (skipInvalidate()) { return; } if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) || (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID || (mPrivateFlags & INVALIDATED) != INVALIDATED) { mPrivateFlags &= ~DRAWING_CACHE_VALID; mPrivateFlags |= INVALIDATED; mPrivateFlags |= DIRTY; final ViewParent p = mParent; final AttachInfo ai = mAttachInfo; //noinspection PointlessBooleanExpression,ConstantConditions if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { if (p != null && ai != null && ai.mHardwareAccelerated) { // fast-track for GL-enabled applications; just invalidate the whole hierarchy // with a null dirty rect, which tells the ViewAncestor to redraw everything p.invalidateChild(this, null); return; } } if (p != null && ai != null && l < r && t < b) { final int scrollX = mScrollX; final int scrollY = mScrollY; final Rect tmpr = ai.mTmpInvalRect; tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY); p.invalidateChild(this, tmpr); } } }
Look at the last five lines of code. When the sliding coordinate system is updated, it takes tflat. set (l-scrollX, t-scrollY, r-scrollX, B-scrollY); after a positive number is input, it is reduced to a negative number. Naturally, it needs to be moved to the left, in this way, they are unified again.
Conclusion: The above is almost the built-in sliding principle of the View, but the slide in the View is instantaneous sliding. There is no transitional effect. Combined with Scroller, you can make a variety of transitional effects. In the next article, I will summarize how to combine Scroller to make the View more dazzling.
Reference: illustrates the scroll principle of android View