English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Preface
In Android development, View has always been a thorn in the side of Android developers. On one hand, they want to advance, on the other hand, they are afraid of advancing. It can be said that Android's View is the biggest stumbling block on the path to advancement, because it involves too many things, such as the View movement we are going to write about this time, as well as the transmission of View touch events, creating custom Views, which are extremely important and must be faced with difficult problems. However, no matter what, difficulties that are not overcome now will be overcome by difficulties in the future.
Before that, let's first understand the definition rules of the Android coordinate system and some position parameters of the View.
Android coordinate system
The position and size of the View are determined by four parameters, namely left, top, right, and bottom, and all four parameters are relative to their parent View.
int width = right-left; int height = bottom-top;
After the layout is completed in the Activity, we can obtain this parameter information through some methods of the View:
//Obtaining the values of left, top, right, and bottom int left = getLeft(); int top = getTop(); int right = getRight(); int bottom = getBottom();
In addition to Android 3.0 later added x, y, translationX, translationY, etc. parameters. (x, y) represents the x, y values at the top left corner of the View in the ViewGroup, translationX and translationY are used to translate a View. The default is all 0, after calling the View's setTranslationX()/After setTranslationY() is called, it changes.
//Obtaining the parameters of x, y, translationX, and translationY int x = getX(); int y = getY(); int translationX = getTranslationX(); int translationY = getTranslationY();
PS: Calling the View's setTranslationX() and setTranslationY() methods can make the View translate a specified distance, but this process is completed instantly. To make the movement of the View smoother, it is therefore possible to use View property animation to specify translationX and translationY.
ObjectAnimator valueAnimator = ObjectAnimator.ofFloat(textView, "translationX", 200); valueAnimator.setDuration(2000); valueAnimator.start();
Additionally, if setTranslationX() and setTranslationY() are set for View, and if the set values do not change, then it will only move once, that is, the first specified movement distance. After checking the source code, we found the reason: originally, after setting the value, it will compare the set value with the current translationX and translationY, and move if they are not consistent.
After understanding some basic parameters of View, let's look at the three types of movement methods of View.
Firstly, using Android system provided scrollTo()/The scrollBy() method implements the movement of View.
Whether it is scrollTo() or scrollBy(), the essence of their movement is View/The content of ViewGroup. And its movement process is completed instantly, therefore, in order to achieve better movement effects, it needs to be used in combination with the Scroller class. In addition, it is different from the Translation above, which moves the View itself, this point needs to be well understood.
scrollTo() and scrollBy() are both methods in View, not in Scroller, but the smooth movement of View is closely related to the Scroller class.
scrollTo() : It refers to the absolute position of the movement, and if the position does not change, multiple calls will not take effect.
Illustration of scrollTo() process
scrollBy() : Its essence is still calling scrollTo(), which refers to the relative distance of the current position (each time, the sum of the current position and the set distance is added and scrollTo() is called, so if you call it multiple times, you will find that it moves a certain distance each time, which is the essential difference from scrollTo()).
Illustration of scrollBy() process
PS:Regarding the above two images, in fact, I have never fully understood what is relative and absolute all along, so the two hand diagrams may be easier to understand. Moreover, there is also the issue of the scrolling direction of scrollTo() and scrollBy(), as we have already drawn the Android coordinate system, where the x-axis is positive from left to right, and the y-axis is positive from top to bottom. However, this does not apply to scrollTo() and scrollBy(), which are exactly the opposite, that is, the x-axis is negative from left to right, and the y-axis is negative from top to bottom, which is simply a bit of a pain in the neck.
Scroller class analysis: and why using the methods in Scroller class can move View/How does ViewGroup content move? Let's try to analyze it.
First
We create an object mScroller of the Scroller class.
Then
To make the View move to the specified position within a specified time, we will call the startScroll() method. startScroll() is a method in the Scroller class, and there is also another commonly used method in the Scroller class, filing(), which mainly deals with smooth movement, generally creating an inertia effect after sliding, making the movement of the View more realistic. Below we will look at the source code of startScroll():
//It receives four/Five parameters. If duration is not set, it will be the default. These four parameters are not difficult to understand, and no further explanation is needed. public void startScroll(int startX, int startY, int dx, int dy, int duration) { ... }
Generally, after calling this method, we need to call View's invalidate() as well, which can trigger the View's draw() method. And draw() calls computeScroll(), in the source code we find that computeScroll() is an empty method, which is why we need to override the computeScroll() method. Because the actual moving operation is performed in computeScroll().
@Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); //It is necessary to call View's postInvalidate()/invalidate(), if not added, will cause the movement of the View to be only in the first frame. postInvalidate(); } super.computeScroll(); }
As we saw above, the Scroller class also has a computeScrollOffset() method, what does it do? Its main function is to determine if mCurrX and mCurrY have changed, returning true if they have and false if they have not. The judgment of this method can indicate whether it is necessary to continuously call scrollTo() to move the View. Here is an example of using scrollTo() to make the View follow the finger movement:
public class CuView extends LinearLayout { private float mStartX; private float mStartY; private Scroller mScroller; /** * Whether the first slide is completed */ private boolean isFirstFinish; public CuView(Context context) { super(context); init(context); } public CuView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { mScroller = new Scroller(context); } public CuView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public CuView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context); } /** * Let the View follow your finger * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: /** * After the first move is completed, we no longer need to get the starting position, otherwise it will cause the View to move to the initial position again. */ if (!isFirstFinish) { mStartX = event.getRawX(); mStartY = event.getRawY(); } break; case MotionEvent.ACTION_MOVE: scrollTo((int) (mStartX - event.getRawX()), (int) (mStartY - event.getRawY()); break; case MotionEvent.ACTION_UP: //First move completed isFirstFinish = true; break; } return true; } /** * Test startScroll */ public void startScroll() { /** * Note the Scroller movement direction, */ mScroller.startScroll(20, 20, -500, -500, 5000); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } super.computeScroll(); } }
2. Use animation to move View
This includes View's Tween Animation/Frame Animation, as well as3Property Animation added after .0, which moves an image of View, and the position and size of the View itself do not change at all.
3. Set View's LayoutParams to move View
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams(); layoutParams.leftMargin = 50; textView.requestLayout();
Summary
That is the summary of the movement of Android View3This contains all the content of the ways, I hope the content of this article can be helpful to everyone when developing Android. If you have any questions, you can leave a message for communication.