Public class MyScrollView extends ViewGroup {
Private int mScreenHeight;
Private Scroller mScroller;
Private int mLastY;
Private int mStart;
Public MyScrollView Context (Context) {
This (context, null);
}
Public MyScrollView (Context Context, AttributeSet attrs) {
This (context, attrs, 0);
}
Public MyScrollView (Context Context, AttributeSet attrs, int defStyleAttr) {
Super (context, attrs, defStyleAttr);
InitView (context);
}
Private void initView Context (Context) {
WindowManager wm=(WindowManager) context. GetSystemService (context. WINDOW_SERVICE);
DisplayMetrics dm=new DisplayMetrics ();
Assert wm!=null;
Wm. GetDefaultDisplay (.) getMetrics (dm);
MScreenHeight=dm. HeightPixels;
MScroller=new Scroller (context);
}
@ Override
Protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
Super. OnMeasure (widthMeasureSpec, heightMeasureSpec);
Int count=getChildCount ();
For (int I=0; i
MeasureChild (childView, widthMeasureSpec, heightMeasureSpec);
}
}
@ Override
Protected void onLayout (Boolean changed, int l, int t, int r, int b) {
Int childCount=getChildCount ();
//set the height of the ViewGroup
MarginLayoutParams MLP=(MarginLayoutParams) getLayoutParams ();
MLP. Height=mScreenHeight * childCount;
SetLayoutParams (MLP);
For (int I=0; i
If (child. GetVisibility ()!=the GONE) {
Child. The layout (l, I * mScreenHeight, r, (I + 1) * mScreenHeight);
}
}
}
@ Override
Public Boolean onTouchEvent (MotionEvent event) {
Int y=(int) event. GetY ();
The switch (event. GetAction ()) {
Case MotionEvent. ACTION_DOWN:
//record touch starting point
MStart=getScrollY ();
MLastY=y;
break;
Case MotionEvent. ACTION_MOVE:
if (! MScroller. IsFinished ()) {
MScroller. AbortAnimation ();
}
Int dy=mLastY - y;
If (getScrollY () & lt; 0 | | getScrollY () & gt; GetHeight () - mScreenHeight) {
Dy=0;
}
ScrollBy (0, dy);
MLastY=y;
break;
Case MotionEvent. ACTION_UP:
//record touch end
Int mEnd=getScrollY ();
Int dScrollY=mEnd - mStart;
If (dScrollY & gt; 0 {
If (dScrollY & lt; MScreenHeight/3) {
MScroller. StartScroll (
0, getScrollY (),
0 - dScrollY);
} else {
MScroller. StartScroll (
0, getScrollY (),
0, mScreenHeight - dScrollY);
}
} else {
If (- dScrollY & lt; MScreenHeight/3) {
MScroller. StartScroll (
0, getScrollY (),
0 - dScrollY);
} else {
MScroller. StartScroll (
0, getScrollY (),
0 - mScreenHeight - dScrollY);
}
}
break;
}
PostInvalidate ();
return true;
}
@ Override
Public void computeScroll () {
Super.com puteScroll ();
If (mScroller.com puteScrollOffset ()) {
ScrollTo (0, mScroller getCurrY ());
PostInvalidate ();
}
}
}
//Mainactivity
Public class MainActivity extends AppCompatActivity {
@ Override
Protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
//activity_main. XML
<? The XML version="1.0" encoding="utf-8"?>
XMLNS: tools="http://schemas.android.com/tools"
Android: layout_width="match_parent"
Android: layout_height="match_parent"
Android: padding="16 dp"
Android: orientation="vertical"
Tools: context="MainActivity" & gt;
Android: layout_height="match_parent" & gt;
Android: layout_height="match_parent"
Android: scaleType="fitXY"
The android: SRC="https://bbs.csdn.net/topics/@drawable/img0"/& gt;
Android: layout_height="match_parent"
Android: scaleType="fitXY"
The android: SRC="https://bbs.csdn.net/topics/@drawable/img1"/& gt;
Android: layout_height="match_parent"
Android: scaleType="fitXY"
The android: SRC="https://bbs.csdn.net/topics/@drawable/img2"/& gt;
Android: layout_height="match_parent"
Android: scaleType="fitXY"
The android: SRC="https://bbs.csdn.net/topics/@drawable/img3"/& gt;