High imitation ink weather pull-down drawing pictures, high imitation ink pull-down drawing
Introduction
I 've been idle recently and I 've learned more. The key is to be sleepy if you don't want to watch something. Moji weather has many things to learn about. In this article, let's talk about the pull-down effect of the "I" Tab. if you pay attention to it, friends like QQ have similar results.
Code Analysis
The code is relatively simple. I overwrite a ScrollView class. Let's talk about its principle first. I first get this ImageView Based on the id, then, get his TopMargin, that is, the masked offset value. When you touch the image, change the TopMargin of the ImageView to produce an effect, when he was relaxed, he made an attribute animation to restore it to the previous position. Okay. That's how it works.
Let's take a look at the layout xml.
<Com. wjj. imagepull. pullScrollView xmlns: android = "http://schemas.android.com/apk/res/android" android: layout_width = "match_parent" android: background = "@ android: color/white" android: id = "@ + id/scroll_view" android: scrollbars = "none" android: layout_height = "match_parent"> <LinearLayout android: orientation = "vertical" android: layout_width = "match_parent" android: layout_height = "match_parent"> <RelativeLayout android: layout_width = "match_parent" android: layout_height = "wrap_content"> <ImageView android: id = "@ + id/pull_img" android: layout_marginTop = "-50dp" android: src = "@ drawable/personal_back" android: layout_width = "match_parent" android: scaleType = "fitXY" android: layout_height = "250dp"/> <ImageView android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: src = "@ drawable/feed_fengfeng" android: scaleType = "fitXY" android: layout_centerInParent = "true"/> </RelativeLayout> // This is omitted ...... </LinearLayout> </com. wjj. imagepull. pullScrollView>
You can see this setting. android: layout_marginTop = "-50dp" is the amount to hide, and the android: id = "@ + id/pull_img" id, don't change it. I just used this ImageView.
On the code
Public class PullScrollView extends ScrollView implements ViewTreeObserver. onGlobalLayoutListener {View view; int preview; float lastY; float offsetY; public PullScrollView (Context context, AttributeSet attrs) {super (context, attrs); ViewTreeObserver observer = getViewTreeObserver (); if (null! = Observer) observer. addOnGlobalLayoutListener (this);} @ Override protected void onFinishInflate () {super. onFinishInflate (); view = findViewById (R. id. pull_img) ;}@ Override public boolean onTouchEvent (MotionEvent ev) {int action = ev. getAction (); float y = ev. getY (); Log. d ("onTouchEvent", "action =" + action + ", y =" + y); MarginLayoutParams params = (MarginLayoutParams) view. getLayoutParams (); swi Tch (action) {case MotionEvent. ACTION_DOWN: lastY = y; break; case MotionEvent. ACTION_MOVE: // calculates the Offset Value of the sliding y direction offsetY = y-lastY; // moves downward if (offsetY> 0) {// slides to see all the images displayed, to the original logic for processing if (params. topMargin = 0) {return super. onTouchEvent (ev);} // when the image is not a drop-down image, move down and hand it to the original logic for processing if (getScrollY ()! = 0) {return super. onTouchEvent (ev);} // you can pull down the image to params. topMargin + = offsetY/10; Log. d ("onTouchEvent", "topMargin" + params. topMargin + ", lastY =" + lastY + ", y =" + y + ", offsetY" + offsetY); if (params. topMargin> = 0) {params. topMargin = 0;} view. setLayoutParams (params); invalidate ();} lastY = y; break; case MotionEvent. ACTION_UP: // if (params. topMargin! =-SrcTopMargion) {Log. d ("ACTION_UP", "moveY =" + (srcTopMargion + params. topMargin); // the difference between the original and current offset values for scrolling. For example: 3 ~ 10 ObjectAnimator animator = ObjectAnimator. ofInt (this, "moveY", params. topMargin,-srcTopMargion); animator. setDuration (200); animator. setInterpolator (new LinearInterpolator (); animator. start () ;}break;} return super. onTouchEvent (ev);}/*** set the Y value in the move ** @ param value */public void setMoveY (int value) {MarginLayoutParams params = (MarginLayoutParams) view. getLayoutParams (); params. topMargin = value; Log. d ("computeScroll", "topMargin =" + params. topMargin); view. setLayoutParams (params); invalidate () ;}@ Override public void onGlobalLayout () {MarginLayoutParams params = (MarginLayoutParams) view. getLayoutParams (); srcTopMargion =-params. topMargin; Log. d ("srcTopMargion", "" + srcTopMargion); getViewTreeObserver (). removeGlobalOnLayoutListener (this );}}
In the PullScrollView constructor, The OnGlobalLayoutListener is registered to listen to the callback after the Tree changes. It is used to obtain the topMargin of the ImageView as the target value for future restoration and obtain the view in onFinishInflate, view = findViewById (R. id. pull_img );
OnTouchEvent is our main battlefield, and the logic is all here. First, we should judge whether the slide is downward in ACTION_MOVE. If so, there are two situations that need to be ruled out, what is the change without topMargin?
The first one is that the topMargin slides to 0, so don't slip.
The second is to slide from other places. For example, when moving down normally, do not handle it.
In addition to the two cases, the topMargin changes. Here I add an offsetY/10 value divided by the 10 value, which means the anti-slide feature is too fast, you can customize this.
When I raise my hand and assume that my topMargin is different from the previous initial value, remember the value we obtained in onGlobalLayout, what needs to be done is to start an animation to slide to the top.
The ObjectAnimator attribute animation is used for automatic sliding. In fact, Scroll is used at the time. Why not use it? Because the rewritten computeScroll method, if it is processed in, it will conflict with your own scrolling. If you are interested, try it.
There is also a setMoveY method, which is the method called by the property animation. The value returned after linear interpolation is calculated and then used to change the topMargin until it is restored to the initial state.
Conclusion
All right, this project is finished, but I only tested it on my Xiaomi mobile phone. I don't know if there will be any problems with other resolutions. You can test it.
Github address
Https://github.com/wu928320442/ImagePull