zoukankan      html  css  js  c++  java
  • Android实现多页左右滑动效果,支持子view动态创建和cache

    要实现多页滑动效果,主要是需要处理onTouchEventonInterceptTouchEvent,要处理好touch事件的子控件和父控件的传递问题。

    滚动控制可以利用androidScroller来实现。

     

    这里提供两种做法:

    1、自定义MFlipper控件,从ViewGroup继承,利用Scroller实现滚动,重点是onTouchEventonInterceptTouchEvent的重写,

    要注意什么时候该返回true,什么时候false。否则会导致界面滑动和界面内按钮点击事件相冲突。

    由于采用了ViewGroup来管理子view,只适合于页面数较少而且较固定的情况,因为viewgroup需要一开始就调用addView,把所有view都加进去并layout

    太多页面会有内存问题。如果是页面很多,而且随时动态增长的话,就需要考虑对viewcache和动态创建,动态layout,具体做法参考下面的方法二;

     

    2、从AdapterView继承,参考Android自带ListView的实现,实现子view动态创建和cache,滑动效果等。

    源码如下:

     

      1. import android.content.Context;  
      2.   
      3. import android.util.AttributeSet;  
      4.   
      5. import android.util.Log;  
      6.   
      7. import android.util.SparseArray;  
      8.   
      9. import android.view.MotionEvent;  
      10.   
      11. import android.view.VelocityTracker;  
      12.   
      13. import android.view.View;  
      14.   
      15. import android.view.ViewConfiguration;  
      16.   
      17. import android.view.ViewGroup;  
      18.   
      19. import android.widget.AdapterView;  
      20.   
      21. import android.widget.BaseAdapter;  
      22.   
      23. import android.widget.Gallery;  
      24.   
      25. import android.widget.Scroller;  
      26.   
      27. /** 
      28.  
      29.  * 自定义一个横向滚动的AdapterView,类似与全屏的Gallery,但是一次只滚动一屏,而且每一屏支持子view的点击处理 
      30.  
      31.  * @author weibinke 
      32.  
      33.  * 
      34.  
      35.  */  
      36.   
      37. public class MultiPageSwitcher extends AdapterView<BaseAdapter> {  
      38.   
      39. private BaseAdapter mAdapter = null;  
      40.   
      41. private Scroller mScroller;  
      42.   
      43. private int mTouchSlop;  
      44.   
      45. private float mTouchStartX;  
      46.   
      47. private float mLastMotionX;  
      48.   
      49. private final static String TAG = "MultiPageSwitcher";  
      50.   
      51. private int mLastScrolledOffset = 0;                  
      52.   
      53. /** User is not touching the list */  
      54.   
      55.     private static final int TOUCH_STATE_RESTING = 0;  
      56.   
      57.     /** User is scrolling the list */  
      58.   
      59. private static final int TOUCH_STATE_SCROLL = 2;  
      60.   
      61. private int mTouchState = TOUCH_STATE_RESTING;  
      62.   
      63. private int mHeightMeasureSpec;  
      64.   
      65. private int mWidthMeasureSpec;  
      66.   
      67. private int mSelectedPosition;  
      68.   
      69. private int mFirstPosition;                                //第一个可见view的position  
      70.   
      71. private int mCurrentSelectedPosition;  
      72.   
      73. private VelocityTracker mVelocityTracker;  
      74.   
      75. private static final int SNAP_VELOCITY = 600;  
      76.   
      77. protected RecycleBin mRecycler = new RecycleBin();  
      78.   
      79. private OnPostionChangeListener mOnPostionChangeListener = null;  
      80.   
      81. public MultiPageSwitcher(Context context, AttributeSet attrs) {  
      82.   
      83. super(context, attrs);  
      84.   
      85. mScroller = new Scroller(context);  
      86.   
      87. mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();  
      88.   
      89. }  
      90.   
      91. @Override  
      92.   
      93. protected void onLayout(boolean changed, int left, int top, int right,  
      94.   
      95. int bottom) {  
      96.   
      97. // TODO Auto-generated method stub  
      98.   
      99. MLog.d("MultiPageSwitcher.onlayout start");  
      100.   
      101. super.onLayout(changed, left, top, right, bottom);  
      102.   
      103. if (mAdapter == null) {  
      104.   
      105. return ;  
      106.   
      107. }  
      108.   
      109. recycleAllViews();  
      110.   
      111. detachAllViewsFromParent();  
      112.   
      113. mRecycler.clear();  
      114.   
      115. fillAllViews();  
      116.   
      117. MLog.d("MultiPageSwitcher.onlayout end");  
      118.   
      119. }  
      120.   
      121. /** 
      122.  
      123.  * 从当前可见的view向左边填充 
      124.  
      125.  */  
      126.   
      127. private void fillToGalleryLeft() {  
      128.   
      129.         int itemSpacing = 0;  
      130.   
      131.         int galleryLeft = 0;  
      132.   
      133.         // Set state for initial iteration  
      134.   
      135.         View prevIterationView = getChildAt(0);  
      136.   
      137.         int curPosition;  
      138.   
      139.         int curRightEdge;  
      140.   
      141.         if (prevIterationView != null) {  
      142.             curPosition = mFirstPosition - 1;  
      143.             curRightEdge = prevIterationView.getLeft() - itemSpacing;  
      144.         } else {  
      145.             // No children available!  
      146.             curPosition = 0;  
      147.             curRightEdge = getRight() - getLeft();  
      148.         }  
      149.   
      150.         while (curRightEdge > galleryLeft && curPosition >= 0) {  
      151.   
      152.             prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,  
      153.   
      154.                     curRightEdge, false);  
      155.   
      156.             // Remember some state  
      157.   
      158.             mFirstPosition = curPosition;  
      159.   
      160.             // Set state for next iteration  
      161.   
      162.             curRightEdge = prevIterationView.getLeft() - itemSpacing;  
      163.   
      164.             curPosition--;  
      165.   
      166.         }  
      167.   
      168.     }  
      169.   
      170.     private void fillToGalleryRight() {  
      171.   
      172.         int itemSpacing = 0;  
      173.   
      174.         int galleryRight = getRight() - getLeft();  
      175.   
      176.         int numChildren = getChildCount();  
      177.   
      178.         int numItems = mAdapter.getCount();  
      179.   
      180.         // Set state for initial iteration  
      181.   
      182.         View prevIterationView = getChildAt(numChildren - 1);  
      183.   
      184.         int curPosition;  
      185.   
      186.         int curLeftEdge;  
      187.   
      188.         if (prevIterationView != null) {  
      189.   
      190.             curPosition = mFirstPosition + numChildren;  
      191.   
      192.             curLeftEdge = prevIterationView.getRight() + itemSpacing;  
      193.   
      194.         } else {  
      195.   
      196.             mFirstPosition = curPosition = numItems - 1;  
      197.   
      198.             curLeftEdge = 0;  
      199.   
      200.         }  
      201.   
      202.         while (curLeftEdge < galleryRight && curPosition < numItems) {  
      203.   
      204.             prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,  
      205.   
      206.                     curLeftEdge, true);  
      207.   
      208.             // Set state for next iteration  
      209.   
      210.             curLeftEdge = prevIterationView.getRight() + itemSpacing;  
      211.   
      212.             curPosition++;  
      213.   
      214.         }  
      215.   
      216.     }  
      217.   
      218. /** 
      219.  
      220.  *填充view 
      221.  
      222.  */  
      223.   
      224. private void fillAllViews(){  
      225.   
      226. //先创建第一个view,使其居中显示  
      227.   
      228. if (mSelectedPosition >= mAdapter.getCount()&& mSelectedPosition > 0) {  
      229.   
      230. //处理被记录被删除导致当前选中位置超出记录数的情况  
      231.   
      232. mSelectedPosition = mAdapter.getCount() - 1;  
      233.   
      234. if(mOnPostionChangeListener != null){  
      235.   
      236. mCurrentSelectedPosition = mSelectedPosition;  
      237.   
      238. mOnPostionChangeListener.onPostionChange(this, mCurrentSelectedPosition);  
      239.   
      240. }  
      241.   
      242. }  
      243.   
      244.    
      245.   
      246. mFirstPosition = mSelectedPosition;  
      247.   
      248. mCurrentSelectedPosition = mSelectedPosition;  
      249.   
      250.    
      251.   
      252. View child = makeAndAddView(mSelectedPosition, 00true);  
      253.   
      254. int offset = getWidth() / 2 - (child.getLeft() + child.getWidth() / 2);  
      255.   
      256. child.offsetLeftAndRight(offset);  
      257.   
      258. fillToGalleryLeft();  
      259.   
      260. fillToGalleryRight();  
      261. }  
      262.   
      263. /** 
      264.  
      265.      * Obtain a view, either by pulling an existing view from the recycler or by 
      266.  
      267.      * getting a new one from the adapter. If we are animating, make sure there 
      268.  
      269.      * is enough information in the view's layout parameters to animate from the 
      270.  
      271.      * old to new positions. 
      272.  
      273.      * 
      274.  
      275.      * @param position Position in the gallery for the view to obtain 
      276.  
      277.      * @param offset Offset from the selected position 
      278.  
      279.      * @param x X-coordintate indicating where this view should be placed. This 
      280.  
      281.      *        will either be the left or right edge of the view, depending on 
      282.  
      283.      *        the fromLeft paramter 
      284.  
      285.      * @param fromLeft Are we posiitoning views based on the left edge? (i.e., 
      286.  
      287.      *        building from left to right)? 
      288.  
      289.      * @return A view that has been added to the gallery 
      290.  
      291.      */  
      292.   
      293.     private View makeAndAddView(int position, int offset, int x,  
      294.   
      295.             boolean fromLeft) {  
      296.   
      297.         View child;  
      298.   
      299.         //ask the adapter for a view  
      300.   
      301.         child = mAdapter.getView(position, nullthis);  
      302.   
      303.         // Position the view  
      304.   
      305.         setUpChild(child, offset, x, fromLeft);  
      306.   
      307.         return child;  
      308.   
      309.     }  
      310.   
      311.     @Override  
      312.   
      313.     protected ViewGroup.LayoutParams generateDefaultLayoutParams() {  
      314.   
      315.         /* 
      316.  
      317.          * Gallery expects Gallery.LayoutParams. 
      318.  
      319.          */  
      320.   
      321.         return new Gallery.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,  
      322.   
      323.                 ViewGroup.LayoutParams.WRAP_CONTENT);  
      324.   
      325.     }  
      326.   
      327.     /** 
      328.  
      329.      * Helper for makeAndAddView to set the position of a view and fill out its 
      330.  
      331.      * layout paramters. 
      332.  
      333.      * 
      334.  
      335.      * @param child The view to position 
      336.  
      337.      * @param offset Offset from the selected position 
      338.  
      339.      * @param x X-coordintate indicating where this view should be placed. This 
      340.  
      341.      *        will either be the left or right edge of the view, depending on 
      342.  
      343.      *        the fromLeft paramter 
      344.  
      345.      * @param fromLeft Are we posiitoning views based on the left edge? (i.e., 
      346.  
      347.      *        building from left to right)? 
      348.  
      349.      */  
      350.   
      351.     private void setUpChild(View child, int offset, int x, boolean fromLeft) {  
      352.   
      353.         // Respect layout params that are already in the view. Otherwise  
      354.   
      355.         // make some up...  
      356.   
      357.         Gallery.LayoutParams lp = (Gallery.LayoutParams)  
      358.   
      359.             child.getLayoutParams();  
      360.   
      361.         if (lp == null) {  
      362.   
      363.             lp = (Gallery.LayoutParams) generateDefaultLayoutParams();  
      364.   
      365.         }  
      366.   
      367.         addViewInLayout(child, fromLeft ? -1 : 0, lp);  
      368.   
      369.         child.setSelected(offset == 0);  
      370.   
      371.         // Get measure specs  
      372.   
      373.         int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec,  
      374.   
      375.                 0, lp.height);  
      376.   
      377.         int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,  
      378.   
      379.                 0, lp.width);  
      380.   
      381.         // Measure child  
      382.   
      383.         child.measure(childWidthSpec, childHeightSpec);  
      384.   
      385.         int childLeft;  
      386.   
      387.         int childRight;  
      388.   
      389.         // Position vertically based on gravity setting  
      390.   
      391.         int childTop = 0;  
      392.   
      393.         int childBottom = childTop + child.getMeasuredHeight();  
      394.   
      395.         int width = child.getMeasuredWidth();  
      396.   
      397.         if (fromLeft) {  
      398.   
      399.             childLeft = x;  
      400.   
      401.             childRight = childLeft + width;  
      402.   
      403.         } else {  
      404.   
      405.             childLeft = x - width;  
      406.   
      407.             childRight = x;  
      408.   
      409.         }  
      410.   
      411.         child.layout(childLeft, childTop, childRight, childBottom);  
      412.   
      413.     }  
      414.   
      415.     @Override  
      416.   
      417.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
      418.   
      419.             // TODO Auto-generated method stub  
      420.   
      421.             super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
      422.   
      423.             mWidthMeasureSpec = widthMeasureSpec;  
      424.   
      425.             mHeightMeasureSpec = heightMeasureSpec;  
      426.   
      427.     }  
      428.   
      429.     @Override  
      430.   
      431.     public int getCount() {  
      432.   
      433.             // TODO Auto-generated method stub  
      434.   
      435.             return mAdapter.getCount();  
      436.   
      437.     }  
      438.   
      439. @Override  
      440.   
      441. public BaseAdapter getAdapter() {  
      442.   
      443. // TODO Auto-generated method stub  
      444.   
      445. return mAdapter;  
      446.   
      447. }  
      448.   
      449.    
      450.   
      451. @Override  
      452.   
      453. public void setAdapter(BaseAdapter adapter) {  
      454.   
      455. // TODO Auto-generated method stub  
      456.   
      457. mAdapter = adapter;  
      458.   
      459. removeAllViewsInLayout();  
      460.   
      461. requestLayout();  
      462.   
      463. }  
      464.   
      465. @Override  
      466.   
      467. public View getSelectedView() {  
      468.   
      469. // TODO Auto-generated method stub  
      470.   
      471. return null;  
      472.   
      473. }  
      474.   
      475.    
      476.   
      477. @Override  
      478.   
      479. public void setSelection(int position) {  
      480.   
      481. // TODO Auto-generated method stub  
      482.   
      483. }  
      484.   
      485. @Override  
      486.   
      487. public boolean onInterceptTouchEvent(MotionEvent event) {  
      488.   
      489. if (!mScroller.isFinished()) {  
      490.   
      491. return true;  
      492.   
      493. }  
      494.   
      495. final int action = event.getAction();  
      496.   
      497. MLog.d("onInterceptTouchEvent action = "+event.getAction());  
      498.   
      499. if (MotionEvent.ACTION_DOWN == action) {  
      500.   
      501. startTouch(event);  
      502.   
      503. return false;  
      504.   
      505. }else if (MotionEvent.ACTION_MOVE == action) {  
      506.   
      507. return startScrollIfNeeded(event);  
      508.   
      509. }else if (MotionEvent.ACTION_UP == action || MotionEvent.ACTION_CANCEL == action) {  
      510.   
      511. mTouchState = TOUCH_STATE_RESTING;  
      512.   
      513. return false;  
      514.   
      515. }  
      516.   
      517. return false;  
      518.   
      519. }  
      520.   
      521. @Override  
      522.   
      523. public boolean onTouchEvent(MotionEvent event) {  
      524.   
      525. if (!mScroller.isFinished()) {  
      526.   
      527. return true;  
      528.   
      529. }  
      530.   
      531. if (mVelocityTracker == null) {  
      532.   
      533. mVelocityTracker = VelocityTracker.obtain();  
      534.   
      535. }  
      536.   
      537. mVelocityTracker.addMovement(event);  
      538.   
      539. MLog.d("onTouchEvent action = "+event.getAction());  
      540.   
      541. final int action = event.getAction();  
      542.   
      543. final float x = event.getX();  
      544.   
      545. if (MotionEvent.ACTION_DOWN == action) {  
      546.   
      547. startTouch(event);  
      548.   
      549. }else if (MotionEvent.ACTION_MOVE == action) {  
      550.   
      551. if (mTouchState == TOUCH_STATE_RESTING) {  
      552.   
      553. startScrollIfNeeded(event);  
      554.   
      555. }else if (mTouchState == TOUCH_STATE_SCROLL) {  
      556.   
      557. int deltaX = (int)(x - mLastMotionX);  
      558.   
      559. mLastMotionX = x;  
      560.   
      561. scrollDeltaX(deltaX);  
      562.   
      563. }  
      564.   
      565. }else if (MotionEvent.ACTION_UP == action || MotionEvent.ACTION_CANCEL == action) {  
      566.   
      567. if (mTouchState == TOUCH_STATE_SCROLL) {  
      568.   
      569. onUp(event);  
      570.   
      571. }  
      572.   
      573. }  
      574.   
      575. return true;  
      576.   
      577. }  
      578.   
      579. private void scrollDeltaX(int deltaX){  
      580.   
      581. //先把现有的view坐标移动  
      582.   
      583. for (int i = 0; i < getChildCount(); i++) {  
      584.   
      585. getChildAt(i).offsetLeftAndRight(deltaX);  
      586.   
      587. }  
      588.   
      589. boolean toLeft = (deltaX < 0);  
      590.   
      591. detachOffScreenChildren(toLeft);  
      592.   
      593. if (deltaX < 0) {  
      594.   
      595. //sroll to right  
      596.   
      597. fillToGalleryRight();  
      598.   
      599. }else {  
      600.   
      601. fillToGalleryLeft();  
      602.   
      603. }  
      604.   
      605. invalidate();  
      606.   
      607. int position = calculteCenterItem() + mFirstPosition;  
      608.   
      609. if (mCurrentSelectedPosition != position) {  
      610.   
      611. mCurrentSelectedPosition = position;  
      612.   
      613. if (mOnPostionChangeListener != null) {  
      614.   
      615. mOnPostionChangeListener.onPostionChange(this, mCurrentSelectedPosition);  
      616.   
      617. }  
      618.   
      619. }  
      620.   
      621. }  
      622.   
      623. private void onUp(MotionEvent event){  
      624.   
      625. final VelocityTracker velocityTracker = mVelocityTracker;    
      626.   
      627. velocityTracker.computeCurrentVelocity(1000);    
      628.   
      629. int velocityX = (int) velocityTracker.getXVelocity();    
      630.   
      631. MLog.d( "onUp velocityX:"+velocityX);  
      632.   
      633. if (velocityX < -SNAP_VELOCITY && mSelectedPosition < mAdapter.getCount() - 1) {  
      634.   
      635. if (scrollToChild(mSelectedPosition + 1)) {  
      636.   
      637. mSelectedPosition ++;  
      638.   
      639. }  
      640.   
      641. }else if (velocityX > SNAP_VELOCITY && mSelectedPosition > 0) {  
      642.   
      643. if (scrollToChild(mSelectedPosition - 1)) {  
      644.   
      645. mSelectedPosition --;  
      646.   
      647. }  
      648.   
      649. }else{  
      650.   
      651. int position = calculteCenterItem();  
      652.   
      653. int newpostion = mFirstPosition + position;  
      654.   
      655. if (scrollToChild(newpostion)) {  
      656.   
      657. mSelectedPosition = newpostion;  
      658.   
      659. }  
      660.   
      661. }  
      662.   
      663. if (mVelocityTracker != null) {    
      664.   
      665.             mVelocityTracker.recycle();    
      666.   
      667.             mVelocityTracker = null;    
      668.   
      669.         }    
      670.   
      671. mTouchState = TOUCH_STATE_RESTING;  
      672.   
      673. }  
      674.   
      675. /** 
      676.  
      677.  * 计算最接近中心点的view 
      678.  
      679.  * @return 
      680.  
      681.  */  
      682.   
      683. private int calculteCenterItem(){  
      684.   
      685. View child = null;  
      686.   
      687. int lastpostion = 0;  
      688.   
      689. int lastclosestDistance = 0;  
      690.   
      691. int viewCenter = getLeft() + getWidth() / 2;  
      692.   
      693. for (int i = 0; i < getChildCount(); i++) {  
      694.   
      695. child = getChildAt(i);  
      696.   
      697. if (child.getLeft() < viewCenter && child.getRight() > viewCenter ) {  
      698.   
      699. lastpostion = i;  
      700.   
      701. break;  
      702.   
      703. }else {  
      704.   
      705. int childClosestDistance = Math.min(Math.abs(child.getLeft() - viewCenter), Math.abs(child.getRight() - viewCenter));  
      706.   
      707. if (childClosestDistance < lastclosestDistance) {  
      708.   
      709. lastclosestDistance = childClosestDistance;  
      710.   
      711. lastpostion = i;  
      712.   
      713. }  
      714.   
      715. }  
      716.   
      717. }  
      718.   
      719. return lastpostion;  
      720.   
      721. }  
      722.   
      723. public void moveNext(){  
      724.   
      725. if (!mScroller.isFinished()) {  
      726.   
      727. return;  
      728.   
      729. }  
      730.   
      731. if (0 <= mSelectedPosition && mSelectedPosition < mAdapter.getCount() - 1) {  
      732.   
      733. if (scrollToChild(mSelectedPosition + 1)) {  
      734.   
      735. mSelectedPosition ++;  
      736.   
      737. }else {  
      738.   
      739. makeAndAddView(mSelectedPosition + 11, getWidth(), true);  
      740.   
      741. if (scrollToChild(mSelectedPosition + 1)) {  
      742.   
      743. mSelectedPosition ++;  
      744.   
      745. }  
      746.   
      747. }  
      748.   
      749. }  
      750.   
      751. }  
      752.   
      753. public void movePrevious(){  
      754.   
      755. if (!mScroller.isFinished()) {  
      756.   
      757. return;  
      758.   
      759. }  
      760.   
      761. if (0 < mSelectedPosition && mSelectedPosition < mAdapter.getCount()) {  
      762.   
      763. if (scrollToChild(mSelectedPosition -1)) {  
      764.   
      765. mSelectedPosition --;  
      766.   
      767. }else {  
      768.   
      769. makeAndAddView(mSelectedPosition - 1, -10false);  
      770.   
      771. mFirstPosition = mSelectedPosition - 1;  
      772.   
      773. if (scrollToChild(mSelectedPosition - 1)) {  
      774.   
      775. mSelectedPosition --;  
      776.   
      777. }  
      778.   
      779. }  
      780.   
      781. }  
      782.   
      783. }  
      784.   
      785. private boolean scrollToChild(int position){  
      786.   
      787. MLog.d( "scrollToChild positionm,FirstPosition,childcount:"+position + "," + mFirstPosition+ "," + getChildCount());  
      788.   
      789. View child = getChildAt(position - mFirstPosition );  
      790.   
      791. if (child != null) {  
      792.   
      793. int distance = getWidth() / 2 - (child.getLeft() + child.getWidth() / 2);  
      794.   
      795. mLastScrolledOffset = 0;  
      796.   
      797. mScroller.startScroll(00, distance, 0,200);  
      798.   
      799. invalidate();  
      800.   
      801. return true;  
      802.   
      803. }  
      804.   
      805. MLog.d( "scrollToChild some error happened");  
      806.   
      807. return false;  
      808.   
      809. }  
      810.   
      811. @Override  
      812.   
      813. public void computeScroll() {  
      814.   
      815. if (mScroller.computeScrollOffset()) {  
      816.   
      817. int scrollX = mScroller.getCurrX();  
      818.   
      819. scrollDeltaX(scrollX - mLastScrolledOffset);  
      820.   
      821. mLastScrolledOffset = scrollX;  
      822.   
      823. postInvalidate();  
      824.   
      825. }  
      826.   
      827. }  
      828.   
      829. private void startTouch(MotionEvent event){  
      830.   
      831. mTouchStartX = event.getX();  
      832.   
      833. mTouchState = mScroller.isFinished()? TOUCH_STATE_RESTING : TOUCH_STATE_SCROLL;  
      834.   
      835. mLastMotionX = mTouchStartX;  
      836.   
      837. }  
      838.   
      839. private boolean startScrollIfNeeded(MotionEvent event){  
      840.   
      841. final int xPos = (int)event.getX();  
      842.   
      843.         mLastMotionX = event.getX();  
      844.   
      845.         if (xPos < mTouchStartX - mTouchSlop  
      846.   
      847.                 || xPos > mTouchStartX + mTouchSlop  
      848.   
      849.               ) {  
      850.   
      851.             // we've moved far enough for this to be a scroll  
      852.   
      853.             mTouchState = TOUCH_STATE_SCROLL;  
      854.   
      855.             return true;  
      856.   
      857.         }  
      858.   
      859.         return false;  
      860.   
      861. }  
      862.   
      863. /** 
      864.  
      865.      * Detaches children that are off the screen (i.e.: Gallery bounds). 
      866.  
      867.      * 
      868.  
      869.      * @param toLeft Whether to detach children to the left of the Gallery, or 
      870.  
      871.      *            to the right. 
      872.  
      873.      */  
      874.   
      875.     private void detachOffScreenChildren(boolean toLeft) {  
      876.   
      877.         int numChildren = getChildCount();  
      878.   
      879.         int start = 0;  
      880.   
      881.         int count = 0;  
      882.   
      883.         int firstPosition = mFirstPosition;  
      884.   
      885.         if (toLeft) {  
      886.   
      887.             final int galleryLeft = 0;  
      888.   
      889.             for (int i = 0; i < numChildren; i++) {  
      890.   
      891.                 final View child = getChildAt(i);  
      892.   
      893.                 if (child.getRight() >= galleryLeft) {  
      894.   
      895.                     break;  
      896.   
      897.                 } else {  
      898.   
      899.                     count++;  
      900.   
      901.                     mRecycler.put(firstPosition + i, child);  
      902.   
      903.                 }  
      904.   
      905.             }  
      906.   
      907.         } else {  
      908.   
      909.             final int galleryRight = getWidth();  
      910.   
      911.             for (int i = numChildren - 1; i >= 0; i--) {  
      912.   
      913.                 final View child = getChildAt(i);  
      914.   
      915.                 if (child.getLeft() <= galleryRight) {  
      916.   
      917.                     break;  
      918.   
      919.                 } else {  
      920.   
      921.                     start = i;  
      922.   
      923.                     count++;  
      924.   
      925.                     mRecycler.put(firstPosition + i, child);  
      926.   
      927.                 }  
      928.   
      929.             }  
      930.   
      931.         }  
      932.   
      933.         detachViewsFromParent(start, count);  
      934.   
      935.         if (toLeft) {  
      936.   
      937.             mFirstPosition += count;  
      938.   
      939.         }  
      940.          
      941.         mRecycler.clear();  
      942.   
      943.     }  
      944.   
      945.     public void setOnPositionChangeListen(OnPostionChangeListener onPostionChangeListener){  
      946.   
      947.             mOnPostionChangeListener = onPostionChangeListener;  
      948.   
      949.     }  
      950.   
      951.     public int getCurrentSelectedPosition(){  
      952.   
      953.             return mCurrentSelectedPosition;  
      954.   
      955.     }  
      956.   
      957.     /** 
      958.  
      959.      * 刷新数据,本来想用AdapterView.AdapterDataSetObserver机制来实现的,但是整个逻辑移植比较麻烦,就暂时用这个替代了 
      960.  
      961.      */  
      962.   
      963.     public void updateData(){  
      964.   
      965.             requestLayout();  
      966.   
      967.     }  
      968.   
      969.     private void recycleAllViews() {  
      970.   
      971.         int childCount = getChildCount();  
      972.   
      973.         final RecycleBin recycleBin = mRecycler;  
      974.   
      975.         // All views go in recycler  
      976.   
      977.         for (int i=0; i<childCount; i++) {  
      978.   
      979.             View v = getChildAt(i);  
      980.   
      981.             int index = mFirstPosition + i;  
      982.   
      983.             recycleBin.put(index, v);  
      984.   
      985.         }   
      986.   
      987.     }  
      988.   
      989.     class RecycleBin {  
      990.   
      991.         private SparseArray<View> mScrapHeap = new SparseArray<View>();  
      992.   
      993.         public void put(int position, View v) {  
      994.   
      995.              if (mScrapHeap.get(position) != null) {  
      996.   
      997.              Log.e(TAG,"RecycleBin put error.");  
      998.   
      999.             }  
      1000.   
      1001.             mScrapHeap.put(position, v);  
      1002.   
      1003.         }  
      1004.   
      1005.         View get(int position) {  
      1006.   
      1007.             // System.out.print("Looking for " + position);  
      1008.   
      1009.             View result = mScrapHeap.get(position);  
      1010.   
      1011.             if (result != null) {  
      1012.   
      1013.                     MLog.d("RecycleBin get hit.");  
      1014.   
      1015.                 mScrapHeap.delete(position);  
      1016.   
      1017.             } else {  
      1018.   
      1019.                     MLog.d("RecycleBin get Miss.");  
      1020.   
      1021.             }  
      1022.   
      1023.             return result;  
      1024.   
      1025.         }  
      1026.   
      1027.         View peek(int position) {  
      1028.   
      1029.             // System.out.print("Looking for " + position);  
      1030.   
      1031.             return mScrapHeap.get(position);  
      1032.   
      1033.         }  
      1034.   
      1035.         void clear() {  
      1036.   
      1037.             final SparseArray<View> scrapHeap = mScrapHeap;  
      1038.   
      1039.             final int count = scrapHeap.size();  
      1040.   
      1041.             for (int i = 0; i < count; i++) {  
      1042.   
      1043.                 final View view = scrapHeap.valueAt(i);  
      1044.   
      1045.                 if (view != null) {  
      1046.   
      1047.                     removeDetachedView(view, true);  
      1048.   
      1049.                 }  
      1050.   
      1051.             }  
      1052.   
      1053.             scrapHeap.clear();  
      1054.   
      1055.         }  
      1056.   
      1057.     }     
      1058.   
      1059.     public interface OnPostionChangeListener{  
      1060.   
      1061.             abstract public void onPostionChange(View v,int position);  
      1062.   
      1063.     }   
      1064.   

  • 相关阅读:
    总结几个 webpack 打包优化的方法,前端项目必备
    vue-cli 3.0 axios 跨域请求代理配置及生产环境 baseUrl 配置
    React之MobX使用
    Couldn't load this key (OpenSSH SSH-2 private key(old PEM format))的解决办法
    HTML基础篇(一,认识HTML)
    Angular学习之路-一、配置项目
    小程序开发日志-3、调用相机竖屏拍照,并将照片转横屏显示
    自定义handsome主题默认文章头图
    DruidDataSource无限重连(mybatis数据源)
    mysql获取表字段信息(字段名,字段长度,字段类型,精度,小数点位)
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/3480791.html
Copyright © 2011-2022 走看看