TopNews is a high imitation of the "Today's Headlines" client

TopNews is a high imitation of the "Today's Headlines" client

Source code introduction: TopNews is a high imitation of the "Today's Headlines" client, 1. slidingmenu side menu 2. UniversalImageLoader Currently the best asynchronous image loading library, powerful configuration, simple to use, can definitely meet your various needs! High imitation of the "Today's Headlines" client, realize most of its functions, practice work, the purpose is to understand how to develop a news client, from the relevant knowledge points involved to improve their own level

Source code effect:

Source code snippet:

  1. package com.jeremyfeinstein.slidingmenu.lib;
  2.   
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.   
  6. import android.content.Context;
  7. import android.graphics.Canvas;
  8. import android.graphics.Rect;
  9. import android.os.Build;
  10. import android.support.v4.view.KeyEventCompat;
  11. import android.support.v4.view.MotionEventCompat;
  12. import android.support.v4.view.VelocityTrackerCompat;
  13. import android.support.v4.view.ViewCompat;
  14. import android.support.v4.view.ViewConfigurationCompat;
  15. import android.util.AttributeSet;
  16. import android.util.FloatMath;
  17. import android.util.Log;
  18. import android.view.FocusFinder;
  19. import android.view.KeyEvent;
  20. import android.view.MotionEvent;
  21. import android.view.SoundEffectConstants;
  22. import android.view.VelocityTracker;
  23. import android.view.View;
  24. import android.view.ViewConfiguration;
  25. import android.view.ViewGroup;
  26. import android.view.animation.Interpolator;
  27. import android.widget.Scroller;
  28.   
  29. import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.OnClosedListener;
  30. import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.OnOpenedListener;
  31. //import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.OnCloseListener;  
  32. //import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.OnOpenListener;  
  33.   
  34. public   class CustomViewAbove extends ViewGroup {
  35.   
  36. private   static   final String TAG = "CustomViewAbove" ;
  37. private   static   final   boolean DEBUG = false ;
  38.   
  39. private   static   final   boolean USE_CACHE = false ;
  40.   
  41. private   static   final   int MAX_SETTLE_DURATION = 600 ; // ms  
  42. private   static   final   int MIN_DISTANCE_FOR_FLING = 25 ; // dips  
  43.   
  44. private   static   final Interpolator sInterpolator = new Interpolator() {
  45. public   float getInterpolation( float t) {
  46. t -= 1.0f ;
  47. return t * t * t * t * t + 1 .0f;
  48. }
  49. };
  50.   
  51. private View mContent;
  52.   
  53. private   int mCurItem;
  54. private Scroller mScroller;
  55.   
  56. private   boolean mScrollingCacheEnabled;
  57.   
  58. private   boolean mScrolling;
  59.   
  60. private   boolean mIsBeingDragged;
  61. private   boolean mIsUnableToDrag;
  62. private   int mTouchSlop;
  63. private   float mInitialMotionX;
  64. /**
  65. * Position of the last motion event.
  66. */  
  67. private   float mLastMotionX;
  68. private   float mLastMotionY;
  69. /**
  70. * ID of the active pointer. This is used to retain consistency during
  71. * drags/flings if multiple pointers are used.
  72. */  
  73. protected   int mActivePointerId = INVALID_POINTER;
  74. /**
  75. * Sentinel value for no current active pointer.
  76. * Used by {@link #mActivePointerId}.
  77. */  
  78. private   static   final   int INVALID_POINTER = - 1 ;
  79.   
  80. /**
  81. * Determines speed during touch scrolling
  82. */  
  83. protectedVelocityTracker mVelocityTracker;
  84. private   int mMinimumVelocity;
  85. protected   int mMaximumVelocity;
  86. private   int mFlingDistance;
  87.   
  88. private CustomViewBehind mViewBehind;
  89. // private int mMode;  
  90. private   boolean mEnabled = true ;
  91.   
  92. private OnPageChangeListener mOnPageChangeListener;
  93. private OnPageChangeListener mInternalPageChangeListener;
  94.   
  95. // private OnCloseListener mCloseListener;  
  96. // private OnOpenListener mOpenListener;  
  97. private OnClosedListener mClosedListener;
  98. private OnOpenedListener mOpenedListener;
  99.   
  100. private List<view> mIgnoredViews = new ArrayList<view>();
  101.   
  102. // private int mScrollState = SCROLL_STATE_IDLE;  
  103.   
  104. /**
  105. * Callback interface for responding to changing state of the selected page.
  106. */  
  107. public   interface OnPageChangeListener {
  108.   
  109. /**
  110. * This method will be invoked when the current page is scrolled, either as part
  111. * of a programmatically initiated smooth scroll or a user initiated touch scroll.
  112. *
  113. * @param position Position index of the first page currently being displayed.
  114. * Page position+1 will be visible if positionOffset is nonzero.
  115. * @param positionOffset Value from [0, 1) indicating the offset from the page at position.
  116. * @param positionOffsetPixels Value in pixels indicating the offset from position.
  117. */  
  118. public   void onPageScrolled( int position, float positionOffset, int positionOffsetPixels);
  119.   
  120. /**
  121. * This method will be invoked when a new page becomes selected. Animation is not
  122. * necessarily complete.
  123. *
  124. * @param position Position index of the new selected page.
  125. */  
  126. public   void onPageSelected( int position);
  127.   
  128. }
  129.   
  130. /**
  131. * Simple implementation of the {@link OnPageChangeListener} interface with stub
  132. * implementations of each method. Extend this if you do not intend to override
  133. * every method of {@link OnPageChangeListener}.
  134. */  
  135. public   static   class SimpleOnPageChangeListener implements OnPageChangeListener {
  136.   
  137. public   void onPageScrolled( int position, float positionOffset, int positionOffsetPixels) {
  138. // This space is for rent  
  139. }
  140.   
  141. public   void onPageSelected( int position) {
  142. // This space is for rent  
  143. }
  144.   
  145. public   void onPageScrollStateChanged( int state) {
  146. // This space is for rent  
  147. }
  148.   
  149. }
  150.   
  151. public CustomViewAbove(Context context) {
  152. this (context, null );
  153. }
  154.   
  155. public CustomViewAbove(Context context, AttributeSet attrs) {
  156. super (context, attrs);
  157. initCustomViewAbove();
  158. }
  159.   
  160. void initCustomViewAbove() {
  161. setWillNotDraw( false );
  162. setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
  163. setFocusable( true );
  164. final Context context = getContext();
  165. mScroller = new Scroller(context, sInterpolator);
  166. final ViewConfiguration configuration = ViewConfiguration.get(context);
  167. mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
  168. mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
  169. mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
  170. setInternalPageChangeListener( new SimpleOnPageChangeListener() {
  171. public   void onPageSelected( int position) {
  172. if (mViewBehind != null ) {
  173. switch (position) {
  174. case   0 :
  175. case   2 :
  176. mViewBehind.setChildrenEnabled( true );
  177. break ;
  178. case   1 :
  179. mViewBehind.setChildrenEnabled( false );
  180. break ;
  181. }
  182. }
  183. }
  184. });
  185.   
  186. final   float density = context.getResources().getDisplayMetrics().density;
  187. mFlingDistance = ( int ) (MIN_DISTANCE_FOR_FLING * density);
  188. }
  189.   
  190. /**
  191. * Set the currently selected page. If the CustomViewPager has already been through its first
  192. * layout there will be a smooth animated transition between the current item and the
  193. * specified item.
  194. *
  195. * @param item Item index to select
  196. */  
  197. public   void setCurrentItem( int item) {
  198. setCurrentItemInternal(item, true , false );
  199. }
  200.   
  201. /**
  202. * Set the currently selected page.
  203. *
  204. * @param item Item index to select
  205. * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately
  206. */  
  207. public   void setCurrentItem( int item, boolean smoothScroll) {
  208. setCurrentItemInternal(item, smoothScroll, false );
  209. }
  210.   
  211. public   int getCurrentItem() {
  212. return mCurItem;
  213. }
  214.   
  215. void setCurrentItemInternal( int item, boolean smoothScroll, boolean always) {
  216. setCurrentItemInternal(item, smoothScroll, always, 0 );
  217. }
  218.   
  219. void setCurrentItemInternal( int item, boolean smoothScroll, boolean always, int velocity) {
  220. if (!always && mCurItem == item) {
  221. setScrollingCacheEnabled( false );
  222. return ;
  223. }
  224.   
  225. item = mViewBehind.getMenuPage(item);
  226.   
  227. final   boolean dispatchSelected = mCurItem != item;
  228. mCurItem = item;
  229. final   int destX = getDestScrollX(mCurItem);
  230. if (dispatchSelected && mOnPageChangeListener != null ) {
  231. mOnPageChangeListener.onPageSelected(item);
  232. }
  233. if (dispatchSelected && mInternalPageChangeListener != null ) {
  234. mInternalPageChangeListener.onPageSelected(item);
  235. }
  236. if (smoothScroll) {
  237. smoothScrollTo(destX, 0 , velocity);
  238. } else {
  239. completeScroll();
  240. scrollTo(destX, 0 );
  241. }
  242. }
  243.   
  244. /**
  245. * Set a listener that will be invoked whenever the page changes or is incrementally
  246. * scrolled. See {@link OnPageChangeListener}.
  247. *
  248. * @param listener Listener to set
  249. */  
  250. public   void setOnPageChangeListener(OnPageChangeListener listener) {
  251. mOnPageChangeListener = listener;
  252. }
  253. /*
  254. public void setOnOpenListener(OnOpenListener l) {
  255. mOpenListener = l;
  256. }
  257.  
  258. public void setOnCloseListener(OnCloseListener l) {
  259. mCloseListener = l;
  260. }
  261. */  
  262. public   void setOnOpenedListener(OnOpenedListener l) {
  263. mOpenedListener = l;
  264. }
  265.   
  266. public   void setOnClosedListener(OnClosedListener l) {
  267. mClosedListener = l;
  268. }
  269.   
  270. /**
  271. * Set a separate OnPageChangeListener for internal use by the support library.
  272. *
  273. * @param listener Listener to set
  274. * @return The old listener that was set, if any.
  275. */  
  276. OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) {
  277. OnPageChangeListener oldListener = mInternalPageChangeListener;
  278. mInternalPageChangeListener = listener;
  279. return oldListener;
  280. }
  281.   
  282. public   void addIgnoredView(View v) {
  283. if (!mIgnoredViews.contains(v)) {
  284. mIgnoredViews.add(v);
  285. }
  286. }
  287.   
  288. public   void removeIgnoredView(View v) {
  289. mIgnoredViews.remove(v);
  290. }
  291.   
  292. public   void clearIgnoredViews() {
  293. mIgnoredViews.clear();
  294. }
  295.   
  296. // We want the duration of the page snap animation to be influenced by the distance that  
  297. // the screen has to travel, however, we don't want this duration to be effected in a  
  298. // purely linear fashion. Instead, we use this method to moderate the effect that the distance  
  299. // of travel has on the overall snap duration.  
  300. float distanceInfluenceForSnapDuration( float f) {
  301. f -= 0 .5f; // center the values ​​about 0.  
  302. f *= 0 .3f * Math.PI / 2 .0f;
  303. return ( float ) FloatMath.sin(f);
  304. }
  305.   
  306. public   int getDestScrollX( int page) {
  307. switch (page) {
  308. case   0 :
  309. case   2 :
  310. return mViewBehind.getMenuLeft(mContent, page);
  311. case   1 :
  312. return mContent.getLeft();
  313. }
  314. return   0 ;
  315. }
  316.   
  317. private   int getLeftBound() {
  318. return mViewBehind.getAbsLeftBound(mContent);
  319. }
  320.   
  321. private   int getRightBound() {
  322. return mViewBehind.getAbsRightBound(mContent);
  323. }
  324.   
  325. public   int getContentLeft() {
  326. return mContent.getLeft() + mContent.getPaddingLeft();
  327. }
  328.   
  329. public   boolean isMenuOpen() {
  330. return mCurItem == 0 || mCurItem == 2 ;
  331. }
  332.   
  333. private   boolean isInIgnoredView(MotionEvent ev) {
  334. Rect rect = new Rect();
  335. for (View v : mIgnoredViews) {
  336. v.getHitRect(rect);
  337. if (rect.contains(( int )ev.getX(), ( int )ev.getY())) return   true ;
  338. }
  339. return   false ;
  340. }
  341.   
  342. public   int getBehindWidth() {
  343. if (mViewBehind == null ) {
  344. return   0 ;
  345. } else {
  346. return mViewBehind.getBehindWidth();
  347. }
  348. }
  349.   
  350. public   int getChildWidth( int i ) {
  351. switch (i) {
  352. case   0 :
  353. return getBehindWidth();
  354. case   1 :
  355. return mContent.getWidth();
  356. default :
  357. return   0 ;
  358. }
  359. }
  360.   
  361. public   boolean isSlidingEnabled() {
  362. return mEnabled;
  363. }
  364.   
  365. public   void setSlidingEnabled( boolean b) {
  366. mEnabled = b;
  367. }
  368.   
  369. /**
  370. * Like {@link View#scrollBy}, but scroll smoothly instead of immediately.
  371. *
  372. * @param x the number of pixels to scroll by on the X axis
  373. * @param y the number of pixels to scroll by on the Y axis
  374. */  
  375. void smoothScrollTo( int x, int y) {
  376. smoothScrollTo(x, y, 0 );
  377. }
  378.   
  379. /**
  380. * Like {@link View#scrollBy}, but scroll smoothly instead of immediately.
  381. *
  382. * @param x the number of pixels to scroll by on the X axis
  383. * @param y the number of pixels to scroll by on the Y axis
  384. * @param velocity the velocity associated with a fling, if applicable. (0 otherwise)
  385. */  
  386. void smoothScrollTo( int x, int y, int velocity) {
  387. if (getChildCount() == 0 ) {
  388. // Nothing to do.  
  389. setScrollingCacheEnabled( false );
  390. return ;
  391. }
  392. int sx = getScrollX();
  393. int sy = getScrollY();
  394. int dx = x - sx;
  395. int dy = y - sy;
  396. if (dx == 0 && dy == 0 ) {
  397. completeScroll();
  398. if (isMenuOpen()) {
  399. if (mOpenedListener != null )
  400. mOpenedListener.onOpened();
  401. } else {
  402. if (mClosedListener != null )
  403. mClosedListener.onClosed();
  404. }
  405. return ;
  406. }
  407.   
  408. setScrollingCacheEnabled( true );
  409. mScrolling = true ;
  410.   
  411. final   int width = getBehindWidth();
  412. final   int halfWidth = width / 2 ;
  413. final   float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width);
  414. final   float distance = halfWidth + halfWidth *
  415. distanceInfluenceForSnapDuration(distanceRatio);
  416.   
  417. int duration = 0 ;
  418. velocity = Math.abs(velocity);
  419. if ( velocity > 0 ) {
  420. duration = 4 * Math.round( 1000 * Math.abs(distance / velocity));
  421. } else {
  422. final   float pageDelta = ( float ) Math.abs(dx) / width;
  423. duration = ( int ) ((pageDelta + 1 ) * 100 );
  424. duration = MAX_SETTLE_DURATION;
  425. }
  426. duration = Math.min(duration, MAX_SETTLE_DURATION);
  427.   
  428. mScroller.startScroll(sx, sy, dx, dy, duration);
  429. invalidate();
  430. }
  431.   
  432. public   void setContent(View v) {
  433. if (mContent != null )
  434. this .removeView(mContent);
  435. mContent = v;
  436. addView(mContent);
  437. }
  438.   
  439. public View getContent() {
  440. return mContent;
  441. }
  442.   
  443. public   void setCustomViewBehind(CustomViewBehind cvb) {
  444. mViewBehind = cvb;
  445. }
  446.   
  447. @Override  
  448. protected   void onMeasure( int widthMeasureSpec, int heightMeasureSpec) {
  449.   
  450. int width = getDefaultSize( 0 , widthMeasureSpec);
  451. int height = getDefaultSize( 0 , heightMeasureSpec);
  452. setMeasuredDimension(width, height);
  453.   
  454. final   int contentWidth = getChildMeasureSpec(widthMeasureSpec, 0 , width);
  455. final   int contentHeight = getChildMeasureSpec(heightMeasureSpec, 0 , height);
  456. mContent.measure(contentWidth, contentHeight);
  457. }
  458.   
  459. @Override  
  460. protected   void onSizeChanged( int w, int h, int oldw, int oldh) {
  461. super .onSizeChanged(w, h, oldw, oldh);
  462. // Make sure scroll position is set correctly.  
  463. if (w != oldw) {
  464. // [ChrisJ] - This fixes the onConfiguration change for orientation issue..  
  465. // maybe worth having a look why the recomputeScroll pos is screwing  
  466. // up?  
  467. completeScroll();
  468. scrollTo(getDestScrollX(mCurItem), getScrollY());
  469. }
  470. }
  471.   
  472. @Override  
  473. protected   void onLayout( boolean changed, int l, int t, int r, int b) {
  474. final   int width = r - l;
  475. final   int height = b - t;
  476. mContent.layout( 0 , 0 , width, height);
  477. }
  478.   
  479. public   void setAboveOffset( int i) {
  480. // RelativeLayout.LayoutParams params = ((RelativeLayout.LayoutParams)mContent.getLayoutParams());  
  481. // params.setMargins(i, params.topMargin, params.rightMargin, params.bottomMargin);  
  482. mContent.setPadding(i, mContent.getPaddingTop(),
  483. mContent.getPaddingRight(), mContent.getPaddingBottom());
  484. }
  485.   
  486.   
  487. @Override  
  488. public   void computeScroll() {
  489. if (!mScroller.isFinished()) {
  490. if (mScroller.computeScrollOffset()) {
  491. int oldX = getScrollX();
  492. int oldY = getScrollY();
  493. int x = mScroller.getCurrX();
  494. int y = mScroller.getCurrY();
  495.   
  496. if (oldX != x || oldY != y) {
  497. scrollTo(x, y);
  498. pageScrolled(x);
  499. }
  500.   
  501. // Keep on drawing until the animation has finished.  
  502. invalidate();
  503. return ;
  504. }
  505. }
  506.   
  507. // Done with scroll, clean up state.  
  508. completeScroll();
  509. }
  510.   
  511. private   void pageScrolled( int xpos) {
  512. final   int widthWithMargin = getWidth();
  513. final   int position = xpos / widthWithMargin;
  514. final   int offsetPixels = xpos % widthWithMargin;
  515. final   float offset = ( float ) offsetPixels / widthWithMargin;
  516.   
  517. onPageScrolled(position, offset, offsetPixels);
  518. }
  519.   
  520. /**
  521. * This method will be invoked when the current page is scrolled, either as part
  522. * of a programmatically initiated smooth scroll or a user initiated touch scroll.
  523. * If you override this method you must call through to the superclass implementation
  524. * (eg super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled
  525. * returns.
  526. *
  527. * @param position Position index of the first page currently being displayed.
  528. * Page position+1 will be visible if positionOffset is nonzero.
  529. * @param offset Value from [0, 1) indicating the offset from the page at position.
  530. * @param offsetPixels Value in pixels indicating the offset from position.
  531. */  
  532. protected   void onPageScrolled( int position, float offset, int offsetPixels) {
  533. if (mOnPageChangeListener != null ) {
  534. mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels);
  535. }
  536. if (mInternalPageChangeListener != null ) {
  537. mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels);
  538. }
  539. }
  540.   
  541. private   void completeScroll() {
  542. boolean needPopulate = mScrolling;
  543. if (needPopulate) {
  544. // Done with scroll, no longer want to cache view drawing.  
  545. setScrollingCacheEnabled( false );
  546. mScroller.abortAnimation();
  547. int oldX = getScrollX();
  548. int oldY = getScrollY();
  549. int x = mScroller.getCurrX();
  550. int y = mScroller.getCurrY();
  551. if (oldX != x || oldY != y) {
  552. scrollTo(x, y);
  553. }
  554. if (isMenuOpen()) {
  555. if (mOpenedListener != null )
  556. mOpenedListener.onOpened();
  557. } else {
  558. if (mClosedListener != null )
  559. mClosedListener.onClosed();
  560. }
  561. }
  562. mScrolling = false ;
  563. }
  564.   
  565. protected   int mTouchMode = SlidingMenu.TOUCHMODE_MARGIN;
  566.   
  567. public   void setTouchMode( int i) {
  568. mTouchMode = i;
  569. }
  570.   
  571. public   int getTouchMode() {
  572. return mTouchMode;
  573. }
  574.   
  575. private   boolean thisTouchAllowed(MotionEvent ev) {
  576. int x = ( int ) (ev.getX() + mScrollX);
  577. if (isMenuOpen()) {
  578. return mViewBehind.menuOpenTouchAllowed(mContent, mCurItem, x);
  579. } else {
  580. switch (mTouchMode) {
  581. case SlidingMenu.TOUCHMODE_FULLSCREEN:
  582. return !isInIgnoredView(ev);
  583. case SlidingMenu.TOUCHMODE_NONE:
  584. return   false ;
  585. case SlidingMenu.TOUCHMODE_MARGIN:
  586. return mViewBehind.marginTouchAllowed(mContent, x);
  587. }
  588. }
  589. return   false ;
  590. }
  591.   
  592. private   boolean thisSlideAllowed( float dx) {
  593. boolean allowed = false ;
  594. if (isMenuOpen()) {
  595. allowed = mViewBehind.menuOpenSlideAllowed(dx);
  596. } else {
  597. allowed = mViewBehind.menuClosedSlideAllowed(dx);
  598. }
  599. if (DEBUG)
  600. Log.v(TAG, "this slide allowed " + allowed + " dx: " + dx);
  601. return allowed;
  602. }
  603.   
  604. private   int getPointerIndex(MotionEvent ev, int id) {
  605. int activePointerIndex = MotionEventCompat.findPointerIndex(ev, id);
  606. if (activePointerIndex == - 1 )
  607. mActivePointerId = INVALID_POINTER;
  608. return activePointerIndex;
  609. }
  610.   
  611. private   boolean mQuickReturn = false ;
  612.   
  613. @Override  
  614. public   boolean onInterceptTouchEvent(MotionEvent ev) {
  615.   
  616. if (!mEnabled)
  617. return   false ;
  618.   
  619. final   int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
  620.   
  621. if (DEBUG)
  622. if (action == MotionEvent.ACTION_DOWN)
  623. Log.v(TAG, "Received ACTION_DOWN" );
  624.   
  625. if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP
  626. || (action != MotionEvent.ACTION_DOWN && mIsUnableToDrag)) {
  627. endDrag();
  628. return   false ;
  629. }
  630.   
  631. switch (action) {
  632. case MotionEvent.ACTION_MOVE:
  633. determineDrag(ev);
  634. break ;
  635. case MotionEvent.ACTION_DOWN:
  636. int index = MotionEventCompat.getActionIndex(ev);
  637. mActivePointerId = MotionEventCompat.getPointerId(ev, index);
  638. if (mActivePointerId == INVALID_POINTER)
  639. break ;
  640. mLastMotionX = mInitialMotionX = MotionEventCompat.getX(ev, index);
  641. mLastMotionY = MotionEventCompat.getY(ev, index);
  642. if (thisTouchAllowed(ev)) {
  643. mIsBeingDragged = false ;
  644. mIsUnableToDrag = false ;
  645. if (isMenuOpen() && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) {
  646. mQuickReturn = true ;
  647. }
  648. } else {
  649. mIsUnableToDrag = true ;
  650. }
  651. break ;
  652. case MotionEventCompat.ACTION_POINTER_UP:
  653. onSecondaryPointerUp(ev);
  654. break ;
  655. }
  656.   
  657. if (!mIsBeingDragged) {
  658. if (mVelocityTracker == null ) {
  659. mVelocityTracker = VelocityTracker.obtain();
  660. }
  661. mVelocityTracker.addMovement(ev);
  662. }
  663. return mIsBeingDragged || mQuickReturn;
  664. }
  665.   
  666.   
  667. @Override  
  668. public   boolean onTouchEvent(MotionEvent ev) {
  669.   
  670. if (!mEnabled)
  671. return   false ;
  672.   
  673. if (!mIsBeingDragged && !thisTouchAllowed(ev))
  674. return   false ;
  675.   
  676. // if (!mIsBeingDragged && !mQuickReturn)  
  677. // return false;  
  678.   
  679. final   int action = ev.getAction();
  680.   
  681. if (mVelocityTracker == null ) {
  682. mVelocityTracker = VelocityTracker.obtain();
  683. }
  684. mVelocityTracker.addMovement(ev);
  685.   
  686. switch (action & MotionEventCompat.ACTION_MASK) {
  687. case MotionEvent.ACTION_DOWN:
  688. /*
  689. * If being flinged and user touches, stop the fling. isFinished
  690. * will be false if being flinged.
  691. */  
  692. completeScroll();
  693.   
  694. // Remember where the motion event started  
  695. int index = MotionEventCompat.getActionIndex(ev);
  696. mActivePointerId = MotionEventCompat.getPointerId(ev, index);
  697. mLastMotionX = mInitialMotionX = ev.getX();
  698. break ;
  699. case MotionEvent.ACTION_MOVE:
  700. if (!mIsBeingDragged) {
  701. determineDrag(ev);
  702. if (mIsUnableToDrag)
  703. return   false ;
  704. }
  705. if (mIsBeingDragged) {
  706. // Scroll to follow the motion event  
  707. final   int activePointerIndex = getPointerIndex(ev, mActivePointerId);
  708. if (mActivePointerId == INVALID_POINTER)
  709. break ;
  710. final   float x = MotionEventCompat.getX(ev, activePointerIndex);
  711. final   float deltaX = mLastMotionX - x;
  712. mLastMotionX = x;
  713. float oldScrollX = getScrollX();
  714. float scrollX = oldScrollX + deltaX;
  715. final   float leftBound = getLeftBound();
  716. final   float rightBound = getRightBound();
  717. if (scrollX < leftBound) {
  718. scrollX = leftBound;
  719. } else   if (scrollX > rightBound) {
  720. scrollX = rightBound;
  721. }
  722. // Don't lose the rounded component  
  723. mLastMotionX += scrollX - ( int ) scrollX;
  724. scrollTo(( int ) scrollX, getScrollY());
  725. pageScrolled(( int ) scrollX);
  726. }
  727. break ;
  728. case MotionEvent.ACTION_UP:
  729. if (mIsBeingDragged) {
  730. final VelocityTracker velocityTracker = mVelocityTracker;
  731. velocityTracker.computeCurrentVelocity( 1000 , mMaximumVelocity);
  732. int initialVelocity = ( int ) VelocityTrackerCompat.getXVelocity(
  733. velocityTracker, mActivePointerId);
  734. final   int scrollX = getScrollX();
  735. // final int widthWithMargin = getWidth();  
  736. // final float pageOffset = (float) (scrollX % widthWithMargin) / widthWithMargin;  
  737. // TODO test this. should get better flinging behavior  
  738. final   float pageOffset = ( float ) (scrollX - getDestScrollX(mCurItem)) / getBehindWidth();
  739. final   int activePointerIndex = getPointerIndex(ev, mActivePointerId);
  740. if (mActivePointerId != INVALID_POINTER) {
  741. final   float x = MotionEventCompat.getX(ev, activePointerIndex);
  742. final   int totalDelta = ( int ) (x - mInitialMotionX);
  743. int nextPage = determineTargetPage(pageOffset, initialVelocity, totalDelta);
  744. setCurrentItemInternal(nextPage, true , true , initialVelocity);
  745. } else {
  746. setCurrentItemInternal(mCurItem, true , true , initialVelocity);
  747. }
  748. mActivePointerId = INVALID_POINTER;
  749. endDrag();
  750. } else   if (mQuickReturn && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) {
  751. // close the menu  
  752. setCurrentItem( 1 );
  753. endDrag();
  754. }
  755. break ;
  756. case MotionEvent.ACTION_CANCEL:
  757. if (mIsBeingDragged) {
  758. setCurrentItemInternal(mCurItem, true , true );
  759. mActivePointerId = INVALID_POINTER;
  760. endDrag();
  761. }
  762. break ;
  763. case MotionEventCompat.ACTION_POINTER_DOWN: {
  764. final   int indexx = MotionEventCompat.getActionIndex(ev);
  765. mLastMotionX = MotionEventCompat.getX(ev, indexx);
  766. mActivePointerId = MotionEventCompat.getPointerId(ev, indexx);
  767. break ;
  768. }
  769. case MotionEventCompat.ACTION_POINTER_UP:
  770. onSecondaryPointerUp(ev);
  771. int pointerIndex = getPointerIndex(ev, mActivePointerId);
  772. if (mActivePointerId == INVALID_POINTER)
  773. break ;
  774. mLastMotionX = MotionEventCompat.getX(ev, pointerIndex);
  775. break ;
  776. }
  777. return   true ;
  778. }
  779.       
  780. private   void determineDrag(MotionEvent ev) {
  781. final   int activePointerId = mActivePointerId;
  782. final   int pointerIndex = getPointerIndex(ev, activePointerId);
  783. if (activePointerId == INVALID_POINTER)
  784. return ;
  785. final   float x = MotionEventCompat.getX(ev, pointerIndex);
  786. final   float dx = x - mLastMotionX;
  787. final   float xDiff = Math.abs(dx);
  788. final   float y = MotionEventCompat.getY(ev, pointerIndex);
  789. final   float dy = y - mLastMotionY;
  790. final   float yDiff = Math.abs(dy);
  791. if (xDiff > (isMenuOpen()?mTouchSlop/ 2 :mTouchSlop) && xDiff > yDiff && thisSlideAllowed(dx)) {
  792. startDrag();
  793. mLastMotionX = x;
  794. mLastMotionY = y;
  795. setScrollingCacheEnabled( true );
  796. // TODO add back in touch slop check  
  797. } else   if (xDiff > mTouchSlop) {
  798. mIsUnableToDrag = true ;
  799. }
  800. }
  801.   
  802. @Override  
  803. public   void scrollTo( int x, int y) {
  804. super .scrollTo(x, y);
  805. mScrollX = x;
  806. mViewBehind.scrollBehindTo(mContent, x, y);
  807. ((SlidingMenu)getParent()).manageLayers(getPercentOpen());
  808. }
  809.   
  810. private   int determineTargetPage( float pageOffset, int velocity, int deltaX) {
  811. int targetPage = mCurItem;
  812. if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) {
  813. if (velocity > 0 && deltaX > 0 ) {
  814. targetPage -= 1 ;
  815. } else   if (velocity < 0 && deltaX < 0 ){
  816. targetPage += 1 ;
  817. }
  818. } else {
  819. targetPage = ( int ) Math.round(mCurItem + pageOffset);
  820. }
  821. return targetPage;
  822. }
  823.   
  824. protected   float getPercentOpen() {
  825. return Math.abs(mScrollX-mContent.getLeft()) / getBehindWidth();
  826. }
  827.   
  828. @Override  
  829. protected   void dispatchDraw(Canvas canvas) {
  830. super .dispatchDraw(canvas);
  831. // Draw the margin drawable if needed.  
  832. mViewBehind.drawShadow(mContent, canvas);
  833. mViewBehind.drawFade(mContent, canvas, getPercentOpen());
  834. mViewBehind.drawSelector(mContent, canvas, getPercentOpen());
  835. }
  836.   
  837. // variables for drawing  
  838. private   float mScrollX = 0.0f ;
  839.   
  840. private   void onSecondaryPointerUp(MotionEvent ev) {
  841. if (DEBUG) Log.v(TAG, "onSecondaryPointerUp called" );
  842. final   int pointerIndex = MotionEventCompat.getActionIndex(ev);
  843. final   int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
  844. if (pointerId == mActivePointerId) {
  845. // This was our active pointer going up. Choose a new  
  846. // active pointer and adjust accordingly.  
  847. final   int newPointerIndex = pointerIndex == 0 ? 1 : 0 ;
  848. mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex);
  849. mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
  850. if (mVelocityTracker != null ) {
  851. mVelocityTracker.clear();
  852. }
  853. }
  854. }
  855.   
  856. private   void startDrag() {
  857. mIsBeingDragged = true ;
  858. mQuickReturn = false ;
  859. }
  860.   
  861. private   void endDrag() {
  862. mQuickReturn = false ;
  863. mIsBeingDragged = false ;
  864. mIsUnableToDrag = false ;
  865. mActivePointerId = INVALID_POINTER;
  866.   
  867. if (mVelocityTracker != null ) {
  868. mVelocityTracker.recycle();
  869. mVelocityTracker = null ;
  870. }
  871. }
  872.   
  873. private   void setScrollingCacheEnabled( boolean enabled) {
  874. if (mScrollingCacheEnabled != enabled) {
  875. mScrollingCacheEnabled = enabled;
  876. if (USE_CACHE) {
  877. final   int size = getChildCount();
  878. for ( int i = 0 ; i < size; ++i) {
  879. final View child = getChildAt(i);
  880. if (child.getVisibility() != GONE) {
  881. child.setDrawingCacheEnabled(enabled);
  882. }
  883. }
  884. }
  885. }
  886. }
  887.   
  888. /**
  889. * Tests scrollability within child views of v given a delta of dx.
  890. *
  891. * @param v View to test for horizontal scrollability
  892. * @param checkV Whether the view v passed should itself be checked for scrollability (true),
  893. * or just its children (false).
  894. * @param dx Delta scrolled in pixels
  895. * @param x X coordinate of the active touch point
  896. * @param y Y coordinate of the active touch point
  897. * @return true if child views of v can be scrolled by delta of dx.
  898. */  
  899. protected   boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
  900. if (v instanceof ViewGroup) {
  901. final ViewGroup group = (ViewGroup) v;
  902. final   int scrollX = v.getScrollX();
  903. final   int scrollY = v.getScrollY();
  904. final   int count = group.getChildCount();
  905. // Count backwards - let topmost views consume scroll distance first.  
  906. for ( int i = count - 1 ; i >= 0 ; i--) {
  907. final View child = group.getChildAt(i);
  908. if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() &&
  909. y + scrollY >= child.getTop() && y + scrollY < child.getBottom() &&
  910. canScroll(child, true , dx, x + scrollX - child.getLeft(),
  911. y + scrollY - child.getTop())) {
  912. return   true ;
  913. }
  914. }
  915. }
  916.   
  917. return checkV && ViewCompat.canScrollHorizontally(v, -dx);
  918. }
  919.   
  920.   
  921. @Override  
  922. public   boolean dispatchKeyEvent(KeyEvent event) {
  923. // Let the focused view and/or our descendants get the key first  
  924. return   super .dispatchKeyEvent(event) || executeKeyEvent(event);
  925. }
  926.   
  927. /**
  928. * You can call this function yourself to have the scroll view perform
  929. * scrolling from a key event, just as if the event had been dispatched to
  930. * it by the view hierarchy.
  931. *
  932. * @param event The key event to execute.
  933. * @return Return true if the event was handled, else false.
  934. */  
  935. public   boolean executeKeyEvent(KeyEvent event) {
  936. boolean handled = false ;
  937. if (event.getAction() == KeyEvent.ACTION_DOWN) {
  938. switch (event.getKeyCode()) {
  939. case KeyEvent.KEYCODE_DPAD_LEFT:
  940. handled = arrowScroll(FOCUS_LEFT);
  941. break ;
  942. case KeyEvent.KEYCODE_DPAD_RIGHT:
  943. handled = arrowScroll(FOCUS_RIGHT);
  944. break ;
  945. case KeyEvent.KEYCODE_TAB:
  946. if (Build.VERSION.SDK_INT >= 11 ) {
  947. // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD  
  948. // before Android 3.0. Ignore the tab key on those devices.  
  949. if (KeyEventCompat.hasNoModifiers(event)) {
  950. handled = arrowScroll(FOCUS_FORWARD);
  951. } else   if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) {
  952. handled = arrowScroll(FOCUS_BACKWARD);
  953. }
  954. }
  955. break ;
  956. }
  957. }
  958. return handled;
  959. }
  960.   
  961. public   boolean arrowScroll( int direction) {
  962. View currentFocused = findFocus();
  963. if (currentFocused == this ) currentFocused = null ;
  964.   
  965. boolean handled = false ;
  966.   
  967. View nextFocused = FocusFinder.getInstance().findNextFocus( this , currentFocused,
  968. direction);
  969. if (nextFocused != null && nextFocused != currentFocused) {
  970. if (direction == View.FOCUS_LEFT) {
  971. handled = nextFocused.requestFocus();
  972. } else   if (direction == View.FOCUS_RIGHT) {
  973. // If there is nothing to the right, or this is causing us to  
  974. // jump to the left, then what we really want to do is page right.  
  975. if (currentFocused != null && nextFocused.getLeft() <= currentFocused.getLeft()) {
  976. handled = pageRight();
  977. } else {
  978. handled = nextFocused.requestFocus();
  979. }
  980. }
  981. } else   if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) {
  982. // Trying to move left and nothing there; try to page.  
  983. handled = pageLeft();
  984. } else   if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) {
  985. // Trying to move right and nothing there; try to page.  
  986. handled = pageRight();
  987. }
  988. if (handled) {
  989. playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
  990. }
  991. return handled;
  992. }
  993.   
  994. boolean pageLeft() {
  995. if (mCurItem > 0 ) {
  996. setCurrentItem(mCurItem- 1 , true );
  997. return   true ;
  998. }
  999. return   false ;
  1000. }
  1001.   
  1002. boolean pageRight() {
  1003. if (mCurItem < 1 ) {
  1004. setCurrentItem(mCurItem+ 1 , true );
  1005. return   true ;
  1006. }
  1007. return   false ;
  1008. }
  1009.   
  1010. }
  1011. </view></view>

Download address: http://download..com/data/2125289

<<:  Mobile phone ordering project source code

>>:  Skylake processors are more likely to be bent? Intel says it's not our fault

Recommend

Can the fast and somewhat brutal Xiaomi 5 still make users get to the climax?

After 19 months of polishing, Xiaomi Mi 5 was fin...

How to choose between GTX 980M and GTX 1060M when the prices are similar?

It's the most troublesome season of the year a...

Are you really ready to raise a dragon in the Year of the Dragon?

Dragons are animals from mythology, and it is pro...

What should I do if I want to quickly sell Didi’s friend links?

Click Sell Friendly Links → My Website page, clic...

What is preventing us from having a sweet love?

Getting a sweet love may be what many young peopl...

The formation of the next supercontinent may not be habitable for mammals

Although the Earth is a sphere, its surface is ma...

Face ID and under-screen fingerprint, Apple's paranoia and Android's tolerance

The dominance of the iPhone seems to be broken, b...

Information flow delivery accounts, advertising positions and advantages

With the continuous development of the Internet, ...