• 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.   

  • 相关阅读:
    HDU 2888 Check Corners (模板题)【二维RMQ】
    POJ 3264 Balanced Lineup(模板题)【RMQ】
    poj 3368 Frequent values(经典)【RMQ】
    SPOJ RPLN (模板题)(ST算法)【RMQ】
    UVA 796 Critical Links(模板题)(无向图求桥)
    UVA 315 Network (模板题)(无向图求割点)
    POJ 2029 Get Many Persimmon Trees (模板题)【二维树状数组】
    poj 3067 Japan 【树状数组】
    POJ 2481 Cows 【树状数组】
    POJ 1195 Mobile phones【二维树状数组】
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/3480791.html
Copyright © 2020-2023  润新知