首页 > 系统 > Android > 正文

android水平循环滚动控件使用详解

2019-10-22 18:18:15
字体:
来源:转载
供稿:网友

本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下

CycleScrollView.java

package com.example.test;  import android.content.Context; import android.graphics.Rect; import android.os.Handler; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Scroller;  @SuppressWarnings("deprecation") public class CycleScrollView<T> extends ViewGroup implements OnGestureListener {    static final String TAG = "CycleScrollView";   Context mContext;    /**    * Scroll velocity.    */   public static final long SCROLL_VELOCITY = 50;    /**    * Scroll offset.    */   public static final int SCROLL_OFFSET = -1;    /**    * Touch delay.    */   public static final long TOUCH_DELAYMILLIS = 2000;    /**    * Fling duration.    */   public static final int FLING_DURATION = 2000;    /**    * Filing max velocity x.    */   public static final int MAX_VELOCITY_X = 1000;    private GestureDetector detector;   private Handler mHandler;   private Scroller mScroller;    /**    * Callback interface adapter and OnItemClick.    */   private CycleScrollAdapter<T> mAdapter;   private OnItemClickListener mOnItemClickListener;    /**    * Scroll index    */   private int mPreIndex;   private int mCurrentIndex;   private int mNextIndex;   private View mCurrentView;   private View mPreView;   private View mNextView;    private float mLastMotionX;    // The reLayout is false can not invoke onLayout.   private boolean reLayout = false;    // If the item count more than screen that can scroll.   private boolean canScroll = false;    // A flag for switch current view.   private boolean mCurrentViewAtLeft = true;    // Fling distance.   private int mFlingX = 0;    private boolean isMoveAction = false;    private int defaultItemY = 10;        private int maxItemCount = 7;    private int initItemX = 20;    /**    * The screen width.    */   private int screenWidth;    /**    * Item view height.    */   private int itemHeight;    /**    * Item view width.    */   private int itemWidth;    /**    * Item view layout x.    */   private int itemX = getInitItemX();    /**    * Item view layout y.    */   private int itemY = defaultItemY;    // Auto scroll view task.   private final Runnable mScrollTask = new Runnable() {      @Override     public void run() {       if (canScroll) {         scrollView(SCROLL_OFFSET);         mHandler.postDelayed(this, SCROLL_VELOCITY);// Loop self.       }     }   };    public CycleScrollView(Context context) {     super(context);     onCreate(context);   }    public CycleScrollView(Context context, AttributeSet attrs) {     super(context, attrs);     onCreate(context);   }    public CycleScrollView(Context context, AttributeSet attrs, int defStyle) {     super(context, attrs, defStyle);     onCreate(context);   }    private void onCreate(Context context) {     mContext = context;     detector = new GestureDetector(this);     mHandler = new Handler();     mScroller = new Scroller(context);   }    /**    * Create scroll index.    */   public void createIndex() {     if (canScroll) {       mPreIndex = maxItemCount - 1;       mCurrentIndex = 0;       mNextIndex = 1;       mPreView = getChildAt(mPreIndex);       mCurrentView = getChildAt(mCurrentIndex);       mNextView = getChildAt(mNextIndex);     }   }    /**    * Set item click callback.    *    * @param onItemClickListener    *      The callback    */   public void setOnItemClickListener(OnItemClickListener onItemClickListener) {     mOnItemClickListener = onItemClickListener;   }    /**    * Set itemAdapter for addItem and bindItem.    *    * @param itemAdapter    */   public void setAdapter(CycleScrollAdapter<T> adapter) {     mAdapter = adapter;   }    /**    * Start auto scroll.    */   public void startScroll() {     if (canScroll) {       mHandler.post(mScrollTask);     }   }    /**    * Stop auto scroll and filing scroll task.    */   public void stopScroll() {     mHandler.removeCallbacks(mScrollTask);   }    /**    * Delay start auto scroll task.    */   public void delayStartScroll() {     if (canScroll) {       mHandler.postDelayed(mScrollTask, TOUCH_DELAYMILLIS);     }   }    @Override   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {     super.onMeasure(widthMeasureSpec, heightMeasureSpec);     int count = this.getChildCount();     for (int i = 0; i < count; i++) {       View child = this.getChildAt(i);       child.measure(widthMeasureSpec, heightMeasureSpec);     }   }    @Override   protected void onLayout(boolean changed, int l, int t, int r, int b) {     /**      * On layout set the child view layout by x y width and height.      */     if (reLayout) {// Run one times.       for (int i = 0; i < getChildCount(); i++) {         View child = this.getChildAt(i);         child.setVisibility(View.VISIBLE);         child.layout(itemX, getItemY(), itemX + getItemWidth(),             getItemY() + getItemHeight());         itemX += getItemMargin();       }       reLayout = !reLayout;     }   }    /**    * When fling view run the fling task scroll view.    */   @Override   public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,       float velocityY) {      if (e1 == null || e2 == null) {       return false;     }      // When deltaX and velocityX not good return false.     if (Math.abs(velocityX) < MAX_VELOCITY_X) {       return false;     }      // Get the delta x.     float deltaX = (e1.getX() - e2.getX());      /**      * If can fling stop other scroll task at first , delay the task after      * fling.      */     mHandler.removeCallbacks(mScrollTask);     if (canScroll) {       mHandler.postDelayed(mScrollTask, TOUCH_DELAYMILLIS           + FLING_DURATION - 1000);     }      /**      * The flingX is fling distance.      */     mFlingX = (int) deltaX;      // Start scroll with fling x.     mScroller.startScroll(0, 0, mFlingX, 0, FLING_DURATION);     return false;   }    @Override   public void computeScroll() {     if (canScroll && mScroller.computeScrollOffset()) {       /**        * The Scroller.getCurrX() approach mFlingX , the deltaX more and        * more small.        */       int deltaX = mFlingX - mScroller.getCurrX();       scrollView(-deltaX / 10);       postInvalidate();     }   }    /**    * When touch event is move scroll child view.    */   @Override   public boolean onTouchEvent(MotionEvent ev) {      // Get event x,y at parent view.     final float x = ev.getX();      /**      * Get event x,y at screen.      */     final int rawX = (int) ev.getRawX();     final int rawY = (int) ev.getRawY();      switch (ev.getAction()) {     case MotionEvent.ACTION_DOWN:       // Reset isMoveAction.       isMoveAction = false;       // Get motionX.       mLastMotionX = x;       break;     case MotionEvent.ACTION_MOVE:       // When action move set isMoveAction true.       isMoveAction = true;       // Only support one pointer.       if (ev.getPointerCount() == 1) {         // Compute delta X.         int deltaX = 0;         deltaX = (int) (x - mLastMotionX);         mLastMotionX = x;         // When canScroll is true, scrollView width deltaX.         if (canScroll) {           scrollView(deltaX);         }       }       break;     case MotionEvent.ACTION_UP:       /**        * If not move find click item and invoke click event.        */       if (!isMoveAction) {         View view = getClickItem(rawX, rawY);         if (view != null) {           mOnItemClickListener.onItemClick(Integer.valueOf(view               .getTag().toString()));         }       }       break;     }     return this.detector.onTouchEvent(ev);   }    /**    * Get click item view by rawX and rawY.    * @param rawX the x at screen.    * @param rawY the y at screen.    * @return the click item view.    */   private View getClickItem(final int rawX, final int rawY) {     for (int i = 0; i < getChildCount(); i++) {       View child = getChildAt(i);       // Get item view rect.       Rect rect = new Rect();       child.getGlobalVisibleRect(rect);       // If click point on the item view, invoke the click event.       if (rect.contains(rawX, rawY)) {         return child;       }     }     return null;   }    /**    * Scroll view by delta x.    *    * @param deltaX    *      The scroll distance.    */   private void scrollView(int deltaX) {     // Move child view by deltaX.     moveChildView(deltaX);     // After move change index.     if (deltaX < 0) {// move left       // If current at right switch current view to left.       switchCurrentViewToLeft();       // change previous current next index.       moveToNext();     } else {// move right       // If current at left switch current view to right.       switchCurrentViewToRight();       // change previous current next index.       moveToPre();     }     invalidate();   }    /**    * Move view by delta x.    *    * @param deltaX    *      The move distance.    */   private void moveChildView(int deltaX) {     for (int i = 0; i < getChildCount(); i++) {       View child = getChildAt(i);       child.layout(child.getLeft() + deltaX, child.getTop(),           child.getRight() + deltaX, child.getBottom());     }   }    /**    * Current event is move to left, if current view at right switch current    * view to left.    */   private void switchCurrentViewToLeft() {     if (!mCurrentViewAtLeft) {       mPreIndex = mCurrentIndex;       mCurrentIndex = mNextIndex;       mNextIndex++;       if (mNextIndex > maxItemCount - 1) {         mNextIndex = 0;       }       mCurrentView = getChildAt(mCurrentIndex);       mPreView = getChildAt(mPreIndex);       mNextView = getChildAt(mNextIndex);       mCurrentViewAtLeft = !mCurrentViewAtLeft;     }   }    /**    * Current event is move to right, if current view at left switch current    * view to right.    */   private void switchCurrentViewToRight() {     if (mCurrentViewAtLeft) {       mNextIndex = mCurrentIndex;       mCurrentIndex = mPreIndex;       mPreIndex--;       if (mPreIndex < 0) {         mPreIndex = maxItemCount - 1;       }       mCurrentView = getChildAt(mCurrentIndex);       mPreView = getChildAt(mPreIndex);       mNextView = getChildAt(mNextIndex);       mCurrentViewAtLeft = !mCurrentViewAtLeft;     }   }    /**    * Current event is move to left,if current view move out of screen move the    * current view to right and reBind the item change index.    */   private void moveToNext() {     if (mCurrentView.getRight() < 0) {       mCurrentView.layout(mPreView.getLeft() + getItemMargin(),           getItemY(), mPreView.getLeft() + getItemMargin()               + getItemWidth(), getItemY() + getItemHeight());        if (mCurrentView.getTag() != null) {         int listIndex = (Integer) mCurrentView.getTag();         int index = (listIndex + maxItemCount) % mAdapter.getCount();         mAdapter.bindView(mCurrentView, mAdapter.get(index));         mCurrentView.setTag(index);       }        mPreIndex = mCurrentIndex;       mCurrentIndex = mNextIndex;       mNextIndex++;       if (mNextIndex > maxItemCount - 1) {         mNextIndex = 0;       }       mCurrentView = getChildAt(mCurrentIndex);       mPreView = getChildAt(mPreIndex);       mNextView = getChildAt(mNextIndex);       moveToNext();     }   }    /**    * Current event is move to right,if current view move out of screen move    * the current view to left and reBind the item change index.    */   private void moveToPre() {     if (mCurrentView.getLeft() > getScreenWidth()) {       mCurrentView.layout(mNextView.getLeft() - getItemMargin(),           getItemY(), mNextView.getLeft() - getItemMargin()               + getItemWidth(), getItemY() + getItemHeight());        if (mCurrentView.getTag() != null) {         int listIndex = (Integer) mCurrentView.getTag();         int index = (listIndex - maxItemCount + mAdapter.getCount())             % mAdapter.getCount();         mAdapter.bindView(mCurrentView, mAdapter.get(index));         mCurrentView.setTag(index);       }        mNextIndex = mCurrentIndex;       mCurrentIndex = mPreIndex;       mPreIndex--;       if (mPreIndex < 0) {         mPreIndex = maxItemCount - 1;       }       mCurrentView = getChildAt(mCurrentIndex);       mPreView = getChildAt(mPreIndex);       mNextView = getChildAt(mNextIndex);       moveToPre();     }   }    @Override   public boolean onDown(MotionEvent e) {     return true;   }    @Override   public void onShowPress(MotionEvent e) {   }    @Override   public boolean onSingleTapUp(MotionEvent e) {     return false;   }    @Override   public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,       float distanceY) {     return false;   }    @Override   public void onLongPress(MotionEvent e) {   }    public int getMaxItemCount() {     return maxItemCount;   }    public void setMaxItemCount(int maxItemCount) {     this.maxItemCount = maxItemCount;   }    public void setReLayout(boolean reLayout) {     this.reLayout = reLayout;   }    public void setCanScroll(boolean canScroll) {     this.canScroll = canScroll;   }    public int getItemX() {     return itemX;   }    public void setItemX(int itemX) {     this.itemX = itemX;   }    public int getItemY() {     return itemY;   }    public void setItemY(int itemY) {     this.itemY = itemY;   }    public int getItemWidth() {     return itemWidth;   }    public void setItemWidth(int itemWidth) {     this.itemWidth = itemWidth;   }    public int getItemHeight() {     return itemHeight;   }    public void setItemHeight(int itemHeight) {     this.itemHeight = itemHeight;   }    public int getItemMargin() {     return (screenWidth - itemWidth * (maxItemCount - 1) - initItemX * 2)/(maxItemCount - 2) + itemWidth;   }    public int getScreenWidth() {     return screenWidth;   }    public void setScreenWidth(int screenWidth) {     this.screenWidth = screenWidth;   }    public int getInitItemX() {     return initItemX;   }    public void setInitItemX(int initItemX) {     this.initItemX = initItemX;   }    /**    * The interface for item click callback.    */   interface OnItemClickListener {     public boolean onItemClick(int position);   }  } 

CycleScrollAdapter.java

package com.example.test;  import java.util.List;  import android.app.Activity; import android.content.Context; import android.util.DisplayMetrics; import android.view.View;  public abstract class CycleScrollAdapter<T> {    private List<T> list;   private CycleScrollView<T> mCycleScrollView;   Context mContext;    /**    * Initial CycleScrollAdapter bind list to view.    *    * @param list    *      The list data.    * @param cycleScrollView    *      The CycleScrollView.    * @param context    *      The Context.    */   public CycleScrollAdapter(List<T> list, CycleScrollView<T> cycleScrollView,       Context context) {     this.list = list;     mContext = context;     mCycleScrollView = cycleScrollView;     mCycleScrollView.setAdapter(this);     GetScreenWidthPixels();     initView(list);   }    /**    * Get screen width pixels.    */   private void GetScreenWidthPixels() {     DisplayMetrics dm = new DisplayMetrics();      Activity a = (Activity) mContext;     a.getWindowManager().getDefaultDisplay().getMetrics(dm);      mCycleScrollView.setScreenWidth(dm.widthPixels);   }    /**    * Bind list to view.    *    * @param list    *      The list data.    */   protected void initView(List<T> list) {     if (list == null || list.size() == 0) {       return;     }          // Clear all view from ViewGroup at first.     mCycleScrollView.removeAllViewsInLayout();      // Loop list.     for (int i = 0; i < list.size(); i++) {       /**        * If list size more than MaxItemCount break the loop, only create        * view count is MaxItemCount.        */       if (i == mCycleScrollView.getMaxItemCount()) {         break;       }        /**        * If list size less than MaxItemCount at the last loop reLayout        * otherwise at the MaxItemCount index reLayout.        */       if (i == list.size() - 1           || i == mCycleScrollView.getMaxItemCount() - 1) {         mCycleScrollView.setItemX(mCycleScrollView.getInitItemX());         mCycleScrollView.setReLayout(true);       }       add(list.get(i), i);     }      /**      * If list count more than MaxItemCount the view can scroll otherwise      * can not scroll.      */     if (list.size() >= mCycleScrollView.getMaxItemCount()) {       mCycleScrollView.setCanScroll(true);     } else {       mCycleScrollView.setCanScroll(false);     }      /**      * If list count more than MaxItemCount reBuild index.      */     mCycleScrollView.createIndex();   }    /**    * Get list size.    *    * @return The list size.    */   public int getCount() {     return list.size();   }    /**    * Returns the element at the specified location in this    *    * @param index    *      the index of the element to return.    * @return the element at the specified location.    */   public T get(int index) {     return list.get(index);   }    /**    * Adds the specified object at the end of this and refresh view.    *    * @param t    *      the object to add.    */   public void addItem(T t) {     list.add(t);     initView(list);   }    /**    * Removes the first occurrence of the specified object from this and    * refresh view.    *    * @param t    *      the object to remove.    */   public void removeItem(T t) {     list.remove(t);     initView(list);   }    /**    * Add the specified view to the index.    *    * @param t    *      The data to add.    * @param index    *      the index.    */   private void add(T t, int index) {     View view = getView(t);     ComputeItemSize(view);     mCycleScrollView.addView(view);     view.setTag(index);   }    /**    * If item size is null compute item size.    *    * @param view    *      the item view.    */   private void ComputeItemSize(View view) {     if (mCycleScrollView.getItemWidth() == 0         || mCycleScrollView.getItemHeight() == 0) {       int w = View.MeasureSpec.makeMeasureSpec(0,           View.MeasureSpec.UNSPECIFIED);       int h = View.MeasureSpec.makeMeasureSpec(0,           View.MeasureSpec.UNSPECIFIED);       view.measure(w, h);       int height = view.getMeasuredHeight();       int width = view.getMeasuredWidth();       mCycleScrollView.setItemHeight(height);       mCycleScrollView.setItemWidth(width);     }   }    /**    * Get item view.    *    * @param t    *      the data need bind to view.    * @return the view.    */   public abstract View getView(T t);    /**    * Bind the item to view.    *    * @param child    *      the item view need bind.    * @param t    *      the item.    */   public abstract void bindView(View child, T t); } 

以上两个是核心类,下面是测试代码。

实现CycleScrollAdapter

AppCycleScrollAdapter.java绑定视图和应用数据

package com.example.test;  import java.util.List;  import android.content.Context; import android.content.pm.PackageInfo; import android.view.View; import android.widget.ImageView; import android.widget.TextView;  public class AppCycleScrollAdapter extends CycleScrollAdapter<PackageInfo> {      public AppCycleScrollAdapter(List<PackageInfo> list,       CycleScrollView<PackageInfo> cycleScrollView, Context context) {     super(list, cycleScrollView, context);   }      @Override   protected void initView(List<PackageInfo> list) {     super.initView(list);   }    @Override   public void bindView(View child, PackageInfo pi) {     ImageView image = (ImageView) child.findViewById(R.id.item_image);     TextView text = (TextView) child.findViewById(R.id.item_text);     image.setImageDrawable(pi.applicationInfo.loadIcon(mContext         .getPackageManager()));     text.setText(pi.applicationInfo.loadLabel(mContext.getPackageManager()));    }    @Override   public View getView(PackageInfo pi) {     View view = View.inflate(mContext, R.layout.view_item, null);     // inflate APP icon view     ImageView image = (ImageView) view.findViewById(R.id.item_image);     // inflate APP name view     TextView text = (TextView) view.findViewById(R.id.item_text);     image.setImageDrawable(pi.applicationInfo.loadIcon(mContext         .getPackageManager()));     text.setText(pi.applicationInfo.loadLabel(mContext.getPackageManager()));     return view;   } } 

入口Activity

package com.example.test;   import java.util.List;   import android.app.Activity; import android.content.pm.PackageInfo; import android.os.Bundle; import android.view.Menu;  public class MainActivity extends Activity{      private CycleScrollView<PackageInfo> mCycleScrollView;   private AppCycleScrollAdapter mAdapter;      @Override   public void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);          mCycleScrollView = ((CycleScrollView<PackageInfo>) this.findViewById(R.id.cycle_scroll_view));      /**      * Get APP list and sort by update time.      */     List<PackageInfo> list = this.getPackageManager()         .getInstalledPackages(0);      mAdapter = new AppCycleScrollAdapter(list, mCycleScrollView, this);        }        @Override   public boolean onCreateOptionsMenu(Menu menu) {     getMenuInflater().inflate(R.menu.activity_main, menu);     return true;   }  } 

布局文件

<?xml version="1.0" encoding="utf-8"?> <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   >    <ImageView     android:id="@+id/item_image"     android:layout_width="60dip"     android:layout_height="60dip"     android:layout_y="5dip"     android:layout_x="10dip"      />    <TextView     android:id="@+id/item_text"     android:layout_width="80dip"     android:layout_height="20dip"     android:layout_y="65dip"     android:layout_x="0dip"     android:gravity="center_horizontal" />  </AbsoluteLayout> [java] view plain copy<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"   xmlns:tools="http://schemas.android.com/tools"   android:layout_width="match_parent"   android:layout_height="match_parent" >    <TextView     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_centerHorizontal="true"     android:layout_centerVertical="true"     android:text="@string/hello_world"     tools:context=".MainActivity" />        <com.example.test.CycleScrollView     android:id="@+id/cycle_scroll_view"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     android:background="#B9000000"     />  </RelativeLayout> 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表