Android 完美的水平方向滑动ListView

在Android开发 中,经常会要用到水平水平ListView(HorizontalListView),但是,Android 官方并没有提供这样一个控件, 所以在这里我给大家分享一下我在项目中用到的一个水平水平ListView,非常好用, 使用过程 中与 ListView 是一样的, 实例化组件, 设置数据,设置Adaper.

package com.example.horizontallistview.hl.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
public abstract class HorizontalListView extends AdapterView<ListAdapter> {
 public HorizontalListView(Context context) {
  super(context);
 }
 public HorizontalListView(Context context, AttributeSet attrs) {
  super(context, attrs);
 }
 public HorizontalListView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
 }
 public abstract int getScreenPositionForView(View view);
 /**
  * Interface definition for a callback to be invoked when an item in this
  * view has been clicked and held.
  */
 public interface OnItemDragListener {
  /**
   * Callback method to be invoked when an item in this view has been
   * dragged outside the vertical tolerance area.
   * 
   * Implementers can call getItemAtPosition(position) if they need to
   * access the data associated with the selected item.
   * 
   * @param parent
   *            The AbsListView where the click happened
   * @param view
   *            The view within the AbsListView that was clicked
   * @param position
   *            The position of the view in the list
   * @param id
   *            The row id of the item that was clicked
   * 
   * @return true if the callback consumed the long click, false otherwise
   */
  boolean onItemStartDrag(AdapterView<?> parent, View view, int position,
    long id);
 }
 public interface OnLayoutChangeListener {
  void onLayoutChange(boolean changed, int left, int top, int right,
    int bottom);
 }
 public interface OnScrollFinishedListener {
  /**
   * Callback method to be invoked when the scroll has completed.
   * 
   * @param currentX
   *            The current scroll position of the view
   */
  void onScrollFinished(int currentX);
 }
}

为什么要继承AdapterView, 大家可以去看看Android提供的ListView是怎么实现的,

 public class ListView extends AbsListView
public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
        ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
        ViewTreeObserver.OnTouchModeChangeListener,
        RemoteViewsAdapter.RemoteAdapterConnectionCallback {

大家 对比去看看官方文档实现 ListView的类就知道了.这里我就不再多说了

大家 注意 HorizontalListView只是 一个抽象类, 所以我们不能直接用它,需要用一个类来实现里面的方法

 public class HorizontalVariableListView extends HorizontalListView implements
  OnGestureListener, FlingRunnableView {
 public enum SelectionMode {
  Single, Multiple
 };
 public interface OnItemClickedListener {
  /**
   * Callback method to be invoked when an item in this AdapterView has
   * been clicked.
   * <p>
   * Implementers can call getItemAtPosition(position) if they need to
   * access the data associated with the selected item.
   * 
   * @param parent
   *            The AdapterView where the click happened.
   * @param view
   *            The view within the AdapterView that was clicked (this
   *            will be a view provided by the adapter)
   * @param position
   *            The position of the view in the adapter.
   * @param id
   *            The row id of the item that was clicked.
   * @return if the implementation return false, then the selection will
   *         not be updated
   */
  boolean onItemClick(AdapterView<?> parent, View view, int position,
    long id);
 }
 public static final int OVER_SCROLL_ALWAYS = 0;
 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
 public static final int OVER_SCROLL_NEVER = 2;
 protected static final String LOG_TAG = "horizontal-variable-list";
 private static final float WIDTH_THRESHOLD = 1.1f;
 protected int mAlignMode = Gravity.CENTER;
 protected SparseBooleanArray mSelectedPositions = new SparseBooleanArray();
 protected int mHeight = 0;
 protected int mPaddingTop = 0;
 protected int mPaddingBottom = 0;
 protected ListAdapter mAdapter;
 private int mAdapterItemCount;
 private int mLeftViewIndex = -1;
 private int mRightViewIndex = 0;
 private GestureDetector mGesture;
 private List<Queue<View>> mRecycleBin;
 private List<Integer> mChildWidths = new ArrayList<Integer>();
 private List<Integer> mChildHeights = new ArrayList<Integer>();
 private boolean mDataChanged = false;
 private IFlingRunnable mFlingRunnable;
 private boolean mForceLayout;
 private int mDragTolerance = 0;
 private boolean mDragScrollEnabled;
 protected EdgeGlow mEdgeGlowLeft, mEdgeGlowRight;
 private int mOverScrollMode = OVER_SCROLL_NEVER;
 private Matrix mEdgeMatrix = new Matrix();
 private ScrollNotifier mScrollNotifier;
 private SelectionMode mChoiceMode = SelectionMode.Single;
 private OnItemSelectedListener mOnItemSelected;
 private OnItemClickedListener mOnItemClicked;
 private OnItemDragListener mItemDragListener;
 private OnScrollChangedListener mScrollListener;
 private OnScrollFinishedListener mScrollFinishedListener;
 private OnLayoutChangeListener mLayoutChangeListener;
 public void setOnItemDragListener(OnItemDragListener listener) {
  mItemDragListener = listener;
 }
 public void setOnScrollListener(OnScrollChangedListener listener) {
  mScrollListener = listener;
 }
 public void setOnLayoutChangeListener(OnLayoutChangeListener listener) {
  mLayoutChangeListener = listener;
 }
 public void setOnScrollFinishedListener(OnScrollFinishedListener listener) {
  mScrollFinishedListener = listener;
 }
 public OnItemDragListener getOnItemDragListener() {
  return mItemDragListener;
 }
 /**
  * Controls how selection is managed within the list.<br />
  * Single or multiple selections are supported
  * 
  * @see SelectionMode
  * @param mode
  *            the selection mode
  */
 public void setSelectionMode(SelectionMode mode) {
  mChoiceMode = mode;
 }
 /**
  * Returns the current selection mode
  * 
  * @see SelectionMode
  * @return
  */
 public SelectionMode getChoiceMode() {
  return mChoiceMode;
 }
 /**
  * Instantiates a new horizontial fixed list view.
  * 
  * @param context
  *            the context
  * @param attrs
  *            the attrs
  */
 public HorizontalVariableListView(Context context, AttributeSet attrs) {
  super(context, attrs);
  initView();
 }
 public HorizontalVariableListView(Context context, AttributeSet attrs,
   int defStyle) {
  super(context, attrs, defStyle);
  initView();
 }
 private synchronized void initView() {
  if (Build.VERSION.SDK_INT > 8) {
   try {
    mFlingRunnable = (IFlingRunnable) ReflectionUtils
      .newInstance(
        "com.iotdc.android.app.shopping.HorizontalVariableListView.widget.Fling9Runnable",
        new Class<?>[] { FlingRunnableView.class,
          int.class }, this, mAnimationDuration);
   } catch (ReflectionException e) {
    mFlingRunnable = new Fling8Runnable(this, mAnimationDuration);
   }
  } else {
   mFlingRunnable = new Fling8Runnable(this, mAnimationDuration);
  }
  mLeftViewIndex = -1;
  mRightViewIndex = 0;
  mMaxX = Integer.MAX_VALUE;
  mMinX = 0;
  mRightEdge = 0;
  mLeftEdge = 0;
  mGesture = new GestureDetector(getContext(), mGestureListener);
  mGesture.setIsLongpressEnabled(false);
  setFocusable(true);
  setFocusableInTouchMode(true);
  ViewConfiguration configuration = ViewConfiguration.get(getContext());
  mTouchSlop = configuration.getScaledTouchSlop();
  mDragTolerance = mTouchSlop;
  mOverscrollDistance = 10;
  mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
  mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
 }
 public void setOverScrollMode(int mode) {
  mOverScrollMode = mode;
  if (mode != OVER_SCROLL_NEVER) {
   if (mEdgeGlowLeft == null) {
    Drawable glow = getContext().getResources().getDrawable(
      R.drawable.overscroll_glow);
    Drawable edge = getContext().getResources().getDrawable(
      R.drawable.overscroll_edge);
    mEdgeGlowLeft = new EdgeGlow(edge, glow);
    mEdgeGlowRight = new EdgeGlow(edge, glow);
    mEdgeGlowLeft.setColorFilter(0xFF33b5e5, Mode.MULTIPLY);
   }
  } else {
   mEdgeGlowLeft = mEdgeGlowRight = null;
  }
 }
 public void setEdgeHeight(int value) {
  mEdgesHeight = value;
 }
 public void setEdgeGravityY(int value) {
  mEdgesGravityY = value;
 }
 @Override
 public void trackMotionScroll(int newX) {
  scrollTo(newX, 0);
  mCurrentX = getScrollX();
  removeNonVisibleItems(mCurrentX);
  fillList(mCurrentX);
  invalidate();
 }
 @Override
 protected void dispatchDraw(Canvas canvas) {
  super.dispatchDraw(canvas);
  if (getChildCount() > 0) {
   drawEdges(canvas);
  }
 }
 .....
 ....
 ....

当然了 , 这个类很复杂,就不把代码贴出来了, 在下面我们把这个demo代码上传的, 希望大家可以去下载,研究,然后把代码整合到自己的项目中使用.

package com.example.horizontallistview;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
import com.example.horizontallistview.hl.widget.HorizontalVariableListView;
import com.example.horizontallistview.hl.widget.HorizontalVariableListView.OnItemClickedListener;
public class MainActivity extends Activity {
 private HorizontalVariableListView lv;
 private MyAdapter adapter;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  lv = (HorizontalVariableListView) findViewById(R.id.lv_horizontal);
  
  String[] items = new String[20];
  
  adapter = new MyAdapter(this, items);
  lv.setAdapter(adapter);
  lv.setSelectionMode(HorizontalVariableListView.SelectionMode.Single);
  
  lv.setOnItemClickedListener(new OnItemClickedListener() {
   
   @Override
   public boolean onItemClick(AdapterView<?> parent, View view, int position,
     long id) {
    // 水平ListView的点击item事件
    Toast.makeText(MainActivity.this, position + "", 1).show();
    return false;
   }
  });
  
 }
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }
}

在Activity中就是这么使用这个控件就行了, 是不是很简单,与Listview是一样的用法

我再把activity_main.xml文件代码贴出来

 <LinearLayout 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"
    android:orientation="vertical"
     >
    <com.example.horizontallistview.hl.widget.HorizontalVariableListView
        android:id="@+id/lv_horizontal"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:gravity="bottom|center_vertical"
        android:paddingBottom="0dp"
        android:paddingTop="0dp" />
</LinearLayout>

下载demo连接:点击下载Android水平水平ListView

你可能感兴趣的:(android,水平ListView)