Flexible layout like apple and Apple
In android development, IOS and android applications are often required to have the same experience. Therefore, many controls need to be defined by developers During android development, the following is an elastic sliding ScrollView similar to Apple.
BounceScrollView source code:
Package com. joke. widget; import android. content. context; import android. graphics. rect; import android. OS. build; import android. util. attributeSet; import android. view. motionEvent; import android. view. view; import android. view. animation. translateAnimation; import android. widget. scrollView;/*** Implementation of ScrollView rebound effect */public class BounceScrollView extends ScrollView {private View inner; // child View private float y; // When the y coordinate is clicked, private Rect normal = new Rect (); // rectangle (this is just a form, only used to determine whether an animation is required .) private boolean isCount = false; // whether to start calculating public BounceScrollView (Context context, AttributeSet attrs) {super (context, attrs ); // deselect the yellow or blue background if (Build. VERSION. SDK_INT> = 9) {this. setOverScrollMode (View. OVER_SCROLL_NEVER) ;}}/***** generate a view based on XML. this function is called at the end of the view generation. After all the child views are added. even if the subclass overwrites the onFinishInflate * method, you should also call To execute this method. */@ Override protected void onFinishInflate () {if (getChildCount ()> 0) {inner = getChildAt (0 );}} /***** listen to touch */@ Override public boolean onTouchEvent (MotionEvent ev) {if (inner! = Null) {commOnTouchEvent (ev);} return super. onTouchEvent (ev);}/*** touch event *** @ param ev */public void commOnTouchEvent (MotionEvent ev) {int action = ev. getAction (); switch (action) {case MotionEvent. ACTION_DOWN: break; case MotionEvent. ACTION_UP: // loosen your finger. if (isNeedAnimation () {animation (); isCount = false;} break;/*** exclude the first moving computation, because the y coordinate cannot be known for the first time, in the MotionEvent. not obtained in ACTION_DOWN, * because it is MyS The crollView touch event is passed to the Child item of LIstView. so it starts from the second calculation. * However, we also need to initialize the sliding distance to 0 when moving for the first time. after the record is accurate, it will be executed normally. */case MotionEvent. ACTION_MOVE: final float preY = y; // The y coordinate float nowY = ev at press time. getY (); // time y coordinate int deltaY = (int) (preY-nowY); // sliding distance if (! IsCount) {deltaY = 0; // here 0 is returned .} y = nowY; // it will not be rolled when it is rolled to the top or bottom. In this case, move the layout if (isNeedMove () {// initialize the header rectangle if (normal. isEmpty () {// Save the normal layout position normal. set (inner. getLeft (), inner. getTop (), inner. getRight (), inner. getBottom ();} // Log. e ("jj", "rectangle:" + inner. getLeft () + "," + inner. getTop () // + "," + inner. getRight () + "," + inner. getBottom (); // move the layout inner. layout (inner. getLeft (), inner. getTop ()-de LtaY/2, inner. getRight (), inner. getBottom ()-deltaY/2);} isCount = true; break; default: break;}/***** contraction animation */public void animation () {// enable the mobile animation TranslateAnimation ta = new TranslateAnimation (0, 0, inner. getTop (), normal. top); ta. setDuration (1, 200); inner. startAnimation (ta); // set to return to the normal layout position inner. layout (normal. left, normal. top, normal. right, normal. bottom); // Log. e ("jj", "regression:" + normal. l Eft + "," + normal. top + "," + // normal. right // + "," + normal. bottom); normal. setEmpty ();} // whether to enable the public boolean isNeedAnimation () {return! Normal. isEmpty ();}/*** whether to move the layout inner. getMeasuredHeight (): Get the total height of the control ** getHeight (): Get the screen height ** @ return */public boolean isNeedMove () {int offset = inner. getMeasuredHeight ()-getHeight (); int scrollY = getScrollY (); // Log. e ("jj", "scrolly =" + scrollY); // 0 is the top, and the back is the bottom if (scrollY = 0 | scrollY = offset) {return true;} return false ;}}
Instructions for use:
1. Directly place the BounceScrollView in the *. widget package.
2. Use BounceScrollView to wrap other la s in the layout file.
<com.joke.widget.BounceScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fadeScrollbars="false" android:fadingEdge="none" android:fadingEdgeLength="0dip" tools:context=".MainActivity" > <!-- android:background="@drawable/coversation_bg" --> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FF0000" android:orientation="vertical" > ... </LinearLayout></com.joke.widget.BounceView>
WorthNote:The BounceScrollView inherits from ScrollView directly. Therefore, the BounceScrollView must follow the ScrollView conventions. Only one subview is allowed in the BounceScrollView. Therefore, a ViewGroup is required for other la S.
In addition, you can add a background to the BounceScrollView and use: android: background = "@ drawable/coversation_bg"
For example, coversation_bg.xml can also overlay images.
<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <bitmap android:src="@drawable/cover_default_bg" android:tileMode="repeat" /> </item> <item android:top="10.0dip"> <bitmap android:gravity="top|center" android:src="@drawable/conversation_bg_logo" /> </item></layer-list>