热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android中实现水平滑动(横向滑动)ListView示例

这篇文章主要介绍了Android中实现水平滑动(横向滑动)ListView示例,本文用自己封装一个控件的方法解决了这个需求,需要的朋友可以参考下

水平的ListView-HorizontalListView的使用

Android中ListView默认的是竖直方向的滑动,由于项目的需求,需要ListView是水平滑动的。有很多的方式可以实现,但是比较好的一种方式就是自己封装一个控件,使用方式和ListView的使用方式是一样的。需要完善的地方:获取到的图片大小没有处理。在界面上展示的是图片的原大小。为了更好的展示效果,应该压缩成统一的尺寸。

HorizontalListView.java 代码如下:

/**
 * 横向的ListView
 * 
 * * @author scd
 * 
 */
public class HorizontalListView extends AdapterView {

  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 mRemovedViewQueue = new LinkedList();
  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  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 

适配器 HorizontalListViewAdapter .java如下:

public class HorizontalListViewAdapter extends BaseAdapter {
  /** 上下文 */
  private Context mContext;
  /** 图像数据源 */
  private ArrayList> mImageList;

  /** 数据源 */
  private ArrayList> mTextList;
  /** Image */
  private static String IMAGE = "ic_";

  private Map mMap = null;

  /** 构造方法 */
  public HorizontalListViewAdapter(Context context) {
    this.mCOntext= context;
    initData();
  }

  /** 初始化数据 */
  public void initData() {
    mImageList = new ArrayList>();
    /*
     * 反射技术
     */
    Class<&#63;> imageClzz = R.drawable.class;
    R.drawable instance = new R.drawable();
    // 取得drawable类中所有的字段
    Field[] fields = imageClzz.getDeclaredFields();
    for (Field field : fields) {
      // 获得字段的名字
      String name = field.getName();
      if (name != null && name.startsWith(IMAGE)) {
        try {
          mMap = new HashMap();
          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 getItem(int position) {

    return mImageList == null &#63; 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 {
    /** 图像 */
    private ImageView mImage;
  }
}


推荐阅读
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 【Windows】实现微信双开或多开的方法及步骤详解
    本文介绍了在Windows系统下实现微信双开或多开的方法,通过安装微信电脑版、复制微信程序启动路径、修改文本文件为bat文件等步骤,实现同时登录两个或多个微信的效果。相比于使用虚拟机的方法,本方法更简单易行,适用于任何电脑,并且不会消耗过多系统资源。详细步骤和原理解释请参考本文内容。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • 安卓select模态框样式改变_微软Office风格的多端(Web、安卓、iOS)组件库——Fabric UI...
    介绍FabricUI是微软开源的一套Office风格的多端组件库,共有三套针对性的组件,分别适用于web、android以及iOS,Fab ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
author-avatar
夏雨之唯美
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有