TopNews高仿“今日头条”客户端

移动开发
TopNews高仿“今日头条”客户端,1.slidingmenu 侧拉菜单 2.UniversalImageLoader 目前最流行的图片异步加载库,配置强大,使用简单,绝对能满足你的各种需求! 高仿“今日头条”客户端,实现它大部分的功能,练习之作,目的了解怎么发开一个新闻类客户端,从涉及的相关知识点中提升自我水平

源码简介:TopNews高仿“今日头条”客户端,1.slidingmenu 侧拉菜单 2.UniversalImageLoader 目前***的图片异步加载库,配置强大,使用简单,绝对能满足你的各种需求! 高仿“今日头条”客户端,实现它大部分的功能,练习之作,目的了解怎么发开一个新闻类客户端,从涉及的相关知识点中提升自我水平

源码效果:

源码片段:

  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.     protected VelocityTracker 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 for rent 
  139.         } 
  140.   
  141.         public void onPageSelected(int position) { 
  142.             // This space for rent 
  143.         } 
  144.   
  145.         public void onPageScrollStateChanged(int state) { 
  146.             // This space 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, truefalse); 
  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(00, 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.      * (e.g. 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, truetrue, initialVelocity); 
  745.                 } else {     
  746.                     setCurrentItemInternal(mCurItem, truetrue, 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, truetrue); 
  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-1true); 
  997.             return true
  998.         } 
  999.         return false
  1000.     } 
  1001.   
  1002.     boolean pageRight() { 
  1003.         if (mCurItem < 1) { 
  1004.             setCurrentItem(mCurItem+1true); 
  1005.             return true
  1006.         } 
  1007.         return false
  1008.     } 
  1009.   
  1010. </view></view> 

下载地址:http://down.51cto.com/data/2125289

责任编辑:倪明 来源: devstore
相关推荐

2015-07-06 10:48:56

iOS开发技巧

2015-07-13 14:05:32

ios开发多表视图

2016-03-03 11:36:09

浪潮

2015-01-09 11:49:26

Android源码下载

2016-05-30 16:13:41

2015-03-30 14:24:06

网易布局

2021-03-19 08:29:30

MacOS操作系统算法

2017-07-10 16:51:42

互联网

2017-09-12 17:05:02

AndroidLoading客户端

2017-08-30 09:42:50

今日头条知乎

2017-11-06 10:45:13

今日头条文本推荐应用

2021-09-22 15:46:29

虚拟桌面瘦客户端胖客户端

2011-08-17 10:10:59

2010-05-31 10:11:32

瘦客户端

2011-03-24 13:00:31

配置nagios客户端

2010-12-21 11:03:15

获取客户端证书

2011-03-02 14:36:24

Filezilla客户端

2011-10-26 13:17:05

2017-12-26 14:00:32

易宝今日头条跨界公益论坛

2009-03-04 10:27:50

客户端组件桌面虚拟化Xendesktop
点赞
收藏

51CTO技术栈公众号