The effect of the rubber band of Path is actually quite good. Here we will record your learning experience.
The core idea of the rubber band should be friction and elasticity. When pulling down, it will simulate a friction effect, and when it is loose, there will be a rebound effect.
Path is to make the part that requires a rubber band effect into the head of the ListView. It is processed in the dispatchTouchEvent of listview.
Let's take a look at the head layout file, which is an ImageView,
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/headView_Main" android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/path_headimage" android:layout_width="fill_parent" android:layout_height="190dp" android:scaleType="center" android:src="@drawable/bg" /></RelativeLayout>
Note that the attribute android: scaleType = "center" is used. It can also be android: scaleType = "centerCrop ". You can try the changes yourself.
Next, let's take a look at the important code section and rewrite a ListView by yourself:
public class ListViewPro extends ListView {private Context mContext;private Scroller mScroller;int left, top;float startX, startY, currentX, currentY;int bgViewH, iv1W;int rootW, rootH;View headView;View bgView;boolean scrollerType;static final int len = 0xc8;public ListViewPro(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public ListViewPro(Context context, AttributeSet attrs) {super(context, attrs);this.mContext = context;mScroller = new Scroller(mContext);}public ListViewPro(Context context) {super(context);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {int action = event.getAction();if (!mScroller.isFinished()) {return super.onTouchEvent(event);}headView = MainActivity.itemHead1;bgView = headView.findViewById(R.id.path_headimage);currentX = event.getX();currentY = event.getY();headView.getTop();switch (action) {case MotionEvent.ACTION_DOWN:left = bgView.getLeft();top = bgView.getBottom();rootW = getWidth();rootH = getHeight();bgViewH = bgView.getHeight();startX = currentX;startY = currentY;break;case MotionEvent.ACTION_MOVE:if (headView.isShown() && headView.getTop() >= 0) {int t = getScrollY(currentY - startY);if (t >= top && t <= headView.getBottom() + len) {bgView.setLayoutParams(new RelativeLayout.LayoutParams(bgView.getWidth(), t));}scrollerType = false;}break;case MotionEvent.ACTION_UP:scrollerType = true;mScroller.startScroll(bgView.getLeft(), bgView.getBottom(),0 - bgView.getLeft(), bgViewH - bgView.getBottom(), 200);invalidate();break;}return super.dispatchTouchEvent(event);} private int getScrollY(float dy) {int yy = (int) (top + dy/2.5F);return yy;}public void computeScroll() {//super.computeScroll();if (mScroller.computeScrollOffset()) {int x = mScroller.getCurrX();int y = mScroller.getCurrY();bgView.layout(0, 0, x + bgView.getWidth(), y);invalidate();if (!mScroller.isFinished() && scrollerType && y > 200) {bgView.setLayoutParams(new RelativeLayout.LayoutParams(bgView.getWidth(), y));}}}}
The principle is to change the height of the ImageView Based on the sliding of the gesture on the ListView. The code processing part is in the case of MotionEvent. ACTION_MOVE of the dispatchTouchEvent method:
int t = getScrollY(currentY - startY);if (t >= top && t <= headView.getBottom() + len) {bgView.setLayoutParams(new RelativeLayout.LayoutParams(bgView.getWidth(), t));}
You need to pay attention to the getScrollY method:
private int getScrollY(float dy) {int yy = (int) (top + dy/2.5F);return yy;}
Dy/2.5 is used to achieve the effect of this rubber band. When the sliding distance of the finger on the ListView is reflected to the height of the ImageView, a virtual Effect of friction is performed.
When the gesture pops up, it will roll to the initial state.