The ListView example implements horizontal (horizontal) sliding in Android

  • 2020-06-23 01:55:47
  • OfStack

Use of horizontal ES1en-ES2en

By default, ListView in Android slides vertically, but due to the requirements of the project, ListView needs to slide horizontally. There are many ways to do this, but a better one is to encapsulate a control in the same way as ListView. What you need to improve: The size of the image you get is not processed. The screen shows the original size of the image. For better display effect, it should be compressed to the size of unit 1.

HorizontalListView. java code is as follows:


/**
 *  horizontal ListView
 * 
 * * @author scd
 * 
 */
public class HorizontalListView extends AdapterView<ListAdapter> {

  public boolean mAlwaysOverrideTouch = true;
  protected ListAdapter mAdapter;
  private int mLeftViewIndex = -1;
  private int mRightViewIndex = 0;
  protected int mCurrentX;
  protected int mNextX;
  private int mMaxX = Integer.MAX_VALUE;
  private int mDisplayOffset = 0;
  protected Scroller mScroller;
  private GestureDetector mGesture;
  private Queue<View> mRemovedViewQueue = new LinkedList<View>();
  private OnItemSelectedListener mOnItemSelected;
  private OnItemClickListener mOnItemClicked;
  private OnItemLongClickListener mOnItemLongClicked;
  private boolean mDataChanged = false;

  public HorizontalListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initView();
  }

  private synchronized void initView() {
    mLeftViewIndex = -1;
    mRightViewIndex = 0;
    mDisplayOffset = 0;
    mCurrentX = 0;
    mNextX = 0;
    mMaxX = Integer.MAX_VALUE;
    mScroller = new Scroller(getContext());
    mGesture = new GestureDetector(getContext(), mOnGesture);
  }

  @Override
  public void setOnItemSelectedListener(
      AdapterView.OnItemSelectedListener listener) {
    mOnItemSelected = listener;
  }

  @Override
  public void setOnItemClickListener(AdapterView.OnItemClickListener listener) {
    mOnItemClicked = listener;
  }

  @Override
  public void setOnItemLongClickListener(
      AdapterView.OnItemLongClickListener listener) {
    mOnItemLongClicked = listener;
  }

  private DataSetObserver mDataObserver = new DataSetObserver() {

    @Override
    public void onChanged() {
      synchronized (HorizontalListView.this) {
        mDataChanged = true;
      }
      invalidate();
      requestLayout();
    }

    @Override
    public void onInvalidated() {
      reset();
      invalidate();
      requestLayout();
    }

  };

  @Override
  public ListAdapter getAdapter() {
    return mAdapter;
  }

  @Override
  public View getSelectedView() {
    // TODO: implement
    return null;
  }

  @Override
  public void setAdapter(ListAdapter adapter) {
    if (mAdapter != null) {
      mAdapter.unregisterDataSetObserver(mDataObserver);
    }
    mAdapter = adapter;
    mAdapter.registerDataSetObserver(mDataObserver);
    reset();
  }

  private synchronized void reset() {
    initView();
    removeAllViewsInLayout();
    requestLayout();
  }

  @Override
  public void setSelection(int position) {
    // TODO: implement
  }

  private void addAndMeasureChild(final View child, int viewPos) {
    LayoutParams params = child.getLayoutParams();
    if (params == null) {
      params = new LayoutParams(LayoutParams.FILL_PARENT,
          LayoutParams.FILL_PARENT);
    }

    addViewInLayout(child, viewPos, params, true);
    child.measure(
        MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
        MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
  }

  @Override
  protected synchronized void onLayout(boolean changed, int left, int top,
      int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    if (mAdapter == null) {
      return;
    }

    if (mDataChanged) {
      int oldCurrentX = mCurrentX;
      initView();
      removeAllViewsInLayout();
      mNextX = oldCurrentX;
      mDataChanged = false;
    }

    if (mScroller.computeScrollOffset()) {
      int scrollx = mScroller.getCurrX();
      mNextX = scrollx;
    }

    if (mNextX <= 0) {
      mNextX = 0;
      mScroller.forceFinished(true);
    }
    if (mNextX >= mMaxX) {
      mNextX = mMaxX;
      mScroller.forceFinished(true);
    }

    int dx = mCurrentX - mNextX;

    removeNonVisibleItems(dx);
    fillList(dx);
    positionItems(dx);

    mCurrentX = mNextX;

    if (!mScroller.isFinished()) {
      post(new Runnable() {
        @Override
        public void run() {
          requestLayout();
        }
      });

    }
  }

  private void fillList(final int dx) {
    int edge = 0;
    View child = getChildAt(getChildCount() - 1);
    if (child != null) {
      edge = child.getRight();
    }
    fillListRight(edge, dx);

    edge = 0;
    child = getChildAt(0);
    if (child != null) {
      edge = child.getLeft();
    }
    fillListLeft(edge, dx);

  }

  private void fillListRight(int rightEdge, final int dx) {
    while (rightEdge + dx < getWidth()
        && mRightViewIndex < mAdapter.getCount()) {

      View child = mAdapter.getView(mRightViewIndex,
          mRemovedViewQueue.poll(), this);
      addAndMeasureChild(child, -1);
      rightEdge += child.getMeasuredWidth();

      if (mRightViewIndex == mAdapter.getCount() - 1) {
        mMaxX = mCurrentX + rightEdge - getWidth();
      }

      if (mMaxX < 0) {
        mMaxX = 0;
      }
      mRightViewIndex++;
    }

  }

  private void fillListLeft(int leftEdge, final int dx) {
    while (leftEdge + dx > 0 && mLeftViewIndex >= 0) {
      View child = mAdapter.getView(mLeftViewIndex,
          mRemovedViewQueue.poll(), this);
      addAndMeasureChild(child, 0);
      leftEdge -= child.getMeasuredWidth();
      mLeftViewIndex--;
      mDisplayOffset -= child.getMeasuredWidth();
    }
  }

  private void removeNonVisibleItems(final int dx) {
    View child = getChildAt(0);
    while (child != null && child.getRight() + dx <= 0) {
      mDisplayOffset += child.getMeasuredWidth();
      mRemovedViewQueue.offer(child);
      removeViewInLayout(child);
      mLeftViewIndex++;
      child = getChildAt(0);

    }

    child = getChildAt(getChildCount() - 1);
    while (child != null && child.getLeft() + dx >= getWidth()) {
      mRemovedViewQueue.offer(child);
      removeViewInLayout(child);
      mRightViewIndex--;
      child = getChildAt(getChildCount() - 1);
    }
  }

  private void positionItems(final int dx) {
    if (getChildCount() > 0) {
      mDisplayOffset += dx;
      int left = mDisplayOffset;
      for (int i = 0; i < getChildCount(); i++) {
        View child = getChildAt(i);
        int childWidth = child.getMeasuredWidth();
        child.layout(left, 0, left + childWidth,
            child.getMeasuredHeight());
        left += childWidth + child.getPaddingRight();
      }
    }
  }

  public synchronized void scrollTo(int x) {
    mScroller.startScroll(mNextX, 0, x - mNextX, 0);
    requestLayout();
  }

  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    boolean handled = super.dispatchTouchEvent(ev);
    handled |= mGesture.onTouchEvent(ev);
    return handled;
  }

  protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
      float velocityY) {
    synchronized (HorizontalListView.this) {
      mScroller.fling(mNextX, 0, (int) -velocityX, 0, 0, mMaxX, 0, 0);
    }
    requestLayout();

    return true;
  }

  protected boolean onDown(MotionEvent e) {
    mScroller.forceFinished(true);
    return true;
  }

  private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() {

    @Override
    public boolean onDown(MotionEvent e) {
      return HorizontalListView.this.onDown(e);
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
        float velocityY) {
      return HorizontalListView.this
          .onFling(e1, e2, velocityX, velocityY);
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2,
        float distanceX, float distanceY) {

      synchronized (HorizontalListView.this) {
        mNextX += (int) distanceX;
      }
      requestLayout();

      return true;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
      for (int i = 0; i < getChildCount(); i++) {
        View child = getChildAt(i);
        if (isEventWithinView(e, child)) {
          if (mOnItemClicked != null) {
            mOnItemClicked.onItemClick(HorizontalListView.this,
                child, mLeftViewIndex + 1 + i,
                mAdapter.getItemId(mLeftViewIndex + 1 + i));
          }
          if (mOnItemSelected != null) {
            mOnItemSelected.onItemSelected(HorizontalListView.this,
                child, mLeftViewIndex + 1 + i,
                mAdapter.getItemId(mLeftViewIndex + 1 + i));
          }
          break;
        }

      }
      return true;
    }

    @Override
    public void onLongPress(MotionEvent e) {
      int childCount = getChildCount();
      for (int i = 0; i < childCount; i++) {
        View child = getChildAt(i);
        if (isEventWithinView(e, child)) {
          if (mOnItemLongClicked != null) {
            mOnItemLongClicked.onItemLongClick(
                HorizontalListView.this, child, mLeftViewIndex
                    + 1 + i,
                mAdapter.getItemId(mLeftViewIndex + 1 + i));
          }
          break;
        }
      }
    }

    private boolean isEventWithinView(MotionEvent e, View child) {
      Rect viewRect = new Rect();
      int[] childPosition = new int[2];
      child.getLocationOnScreen(childPosition);
      int left = childPosition[0];
      int right = left + child.getWidth();
      int top = childPosition[1];
      int bottom = top + child.getHeight();
      viewRect.set(left, top, right, bottom);
      return viewRect.contains((int) e.getRawX(), (int) e.getRawY());
    }
  };

}

Adapter ES16en. java is as follows:


public class HorizontalListViewAdapter extends BaseAdapter {
  /**  context  */
  private Context mContext;
  /**  Image data source  */
  private ArrayList<Map<String, Integer>> mImageList;

  /**  The data source  */
  private ArrayList<Map<String, Integer>> mTextList;
  /** Image */
  private static String IMAGE = "ic_";

  private Map<String, Integer> mMap = null;

  /**  A constructor  */
  public HorizontalListViewAdapter(Context context) {
    this.mContext = context;
    initData();
  }

  /**  Initialization data  */
  public void initData() {
    mImageList = new ArrayList<Map<String, Integer>>();
    /*
     *  Reflection technology 
     */
    Class<?> imageClzz = R.drawable.class;
    R.drawable instance = new R.drawable();
    //  achieve drawable All the fields in the class 
    Field[] fields = imageClzz.getDeclaredFields();
    for (Field field : fields) {
      //  Gets the name of the field 
      String name = field.getName();
      if (name != null && name.startsWith(IMAGE)) {
        try {
          mMap = new HashMap<String, Integer>();
          mMap.put(IMAGE, (Integer) field.get(instance));
          mImageList.add(mMap);
        } catch (IllegalAccessException e) {
          e.printStackTrace();
        }
      }

    }
  }


  @Override
  public int getCount() {
    return mImageList.size();
  }

  @Override
  public Map<String, Integer> getItem(int position) {

    return mImageList == null ? null : mImageList.get(position);
  }

  @Override
  public long getItemId(int position) {
    return position;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {

    ViewHolder holder;
    if (convertView == null) {
      holder = new ViewHolder();
      convertView = LayoutInflater.from(mContext).inflate(
          R.layout.horizontal_list_item, null);
      holder.mImage = (ImageView) convertView
          .findViewById(R.id.iv_list_item);
      holder.mTitle = (TextView) convertView
          .findViewById(R.id.tv_list_item);
      convertView.setTag(holder);
    } else {
      holder = (ViewHolder) convertView.getTag();
    }

    if (position == mSelectIndex) {
      convertView.setSelected(true);
    } else {
      convertView.setSelected(false);
    }
    holder.mImage.setImageResource(getItem(position).get(IMAGE));
    return convertView;
  }

  private class ViewHolder {
    /**  image  */
    private ImageView mImage;
  }
}


Related articles: