欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android开发实现自定义水平滚动的容器示例

程序员文章站 2024-02-11 17:26:40
本文实例讲述了android开发实现自定义水平滚动的容器。分享给大家供大家参考,具体如下: public class horizontalscrollview e...

本文实例讲述了android开发实现自定义水平滚动的容器。分享给大家供大家参考,具体如下:

public class horizontalscrollview extends viewgroup {
  //手势
  private gesturedetector mgesturedetector;
  private horizontalscroller mscroller;
  private int curid;
  //快速滑动
  private boolean isflying;
  //--回调函数-------------------------------------
  private onchangelistener mlistener;
  public void setonchangelistener(onchangelistener listener) {
    if (listener != null) {
      mlistener = listener;
    }
  }
  public interface onchangelistener{
    void move2dest(int curid);
  }
  public horizontalscrollview(context context) {
    this(context, null);
  }
  public horizontalscrollview(context context, attributeset attrs) {
    this(context, attrs, 0);
  }
  public horizontalscrollview(context context, attributeset attrs, int defstyle) {
    super(context, attrs, defstyle);
    mscroller = new horizontalscroller();
    isflying = false;
    initgesture(context);
  }
  @override
  protected void onlayout(boolean changed, int l, int t, int r, int b) {
    // 模向移动,
    for (int i = 0; i < getchildcount(); i++) {
      view view = getchildat(i);
      //给水平方向的每个view定位
      view.layout(i * getwidth(), 0, getwidth() + i * getwidth(), getheight());
    }
  }
  @override
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
    for (int i = 0; i < getchildcount(); i++) {
      view view = getchildat(i);
      view.measure(widthmeasurespec, heightmeasurespec);
    }
    super.onmeasure(widthmeasurespec, heightmeasurespec);
  }
  @override
  public boolean ontouchevent(motionevent event) {
    mgesturedetector.ontouchevent(event);
    switch (event.getaction()) {
    case motionevent.action_down:
      if (!isflying) {
        move2dest();
      }
      isflying = false;
      break;
    case motionevent.action_move:
      break;
    case motionevent.action_up:
      break;
    default:
      break;
    }
    return true;
  }
  public void move2dest() {
    //
    int destid = (getscrollx() + getwidth() / 2) / getwidth();
    move2dest(destid);
  }
  public void move2dest(int destid) {
    curid = destid;
    if (destid > getchildcount() - 1) {
      destid = getchildcount() - 1;
    }
    if (mlistener != null) {
      mlistener.move2dest(curid);
    }
    int distance = (int) (destid * getwidth() - getscrollx());
    // scrollby(distance, 0);
    mscroller.startscroll(getscrollx(), getscrolly(), distance, 0);
    invalidate();
  }
  /**
   * invalidate()此方法会触发下面的方法
   */
  @override
  public void computescroll() {
    // 如果存在偏移,就不断刷新
    if (mscroller.computescrolloffset()) {
      scrollto(mscroller.getcurrx(), 0);
      invalidate();
    }
    super.computescroll();
  }
  private void initgesture(context context) {
    mgesturedetector = new gesturedetector(context, new ongesturelistener() {
      @override
      public boolean onsingletapup(motionevent e) {
        return false;
      }
      @override
      public void onshowpress(motionevent e) {
      }
      @override
      public boolean onscroll(motionevent e1, motionevent e2, float distancex, float distancey) {
        scrollby((int) distancex, 0);
        return false;
      }
      @override
      public void onlongpress(motionevent e) {
      }
      @override
      /**
       * 快速滑动时
       */
      public boolean onfling(motionevent e1, motionevent e2, float velocityx, float velocityy) {
        isflying = true;
        if (curid > 0 && velocityx > 0) {// 表示向左移
          move2dest(curid - 1);
        } else if (curid < getchildcount() && velocityx < 0) {
          move2dest(curid + 1);// 向右
        } else {
          move2dest();// 移到原位
        }
        return false;
      }
      @override
      public boolean ondown(motionevent e) {
        return false;
      }
    });
  }
}

/**
 * 位移计算工具类
 *
 * @author chenlin
 *
 */
public class horizontalscroller {
  private int startx;
  private int starty;
  private int distancex;
  private int distancey;
  private int currentx;
  private int currenty;
  private long starttime;
  private long duration = 1000l;
  private boolean isfinish;
  /**
   *
   * @param scrollx
   *      x坐标
   * @param scrolly
   *      y坐标
   * @param distancex
   *      x方向移动的距离
   * @param distancey
   *      y方向移动的距离
   */
  public void startscroll(int scrollx, int scrolly, int distancex, int distancey) {
    startx = scrollx;
    starty = scrolly;
    this.distancex = distancex;
    this.distancey = distancey;
    isfinish = false;
    starttime = systemclock.uptimemillis();
  }
  /**
   * 计算偏移量,
   *
   * @return true 还在移动 false:移动已经停止
   */
  public boolean computescrolloffset() {
    if (isfinish) {
      return false;
    }
    long timepassed = systemclock.uptimemillis() - starttime;
    if (timepassed < duration) {
      currentx = (int) (startx + distancex * timepassed / duration);
      currenty = (int) (starty + distancey * timepassed / duration);
      system.out.println("currentx:::" + currentx);
    } else if (timepassed >= duration) {
      currentx = startx + distancex;
      currenty = starty + distancey;
      isfinish = true;
    }
    return true;
  }
  public int getcurrx() {
    return currentx;
  }
  public void setcurrentx(int currentx) {
    this.currentx = currentx;
  }
  public int getcurrenty() {
    return currenty;
  }
  public void setcurrenty(int currenty) {
    this.currenty = currenty;
  }
}

使用方法

public class scrollactivity extends activity implements oncheckedchangelistener, onchangelistener {
  private int[] ids = { r.drawable.a1, r.drawable.a2, r.drawable.a3, r.drawable.a4, r.drawable.a5, r.drawable.a6 };
  private horizontalscrollview mview;
  private linearlayout mlayout;
  private radiogroup mgroup;
  @override
  protected void oncreate(bundle savedinstancestate) {
    requestwindowfeature(window.feature_no_title);
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_myscrollview);
    init();
  }
  private void init() {
    mlayout = (linearlayout) findviewbyid(r.id.body_layout);
    mgroup = (radiogroup) findviewbyid(r.id.radiogroup);
    mview = new horizontalscrollview(this);
    for (int i = 0; i < ids.length; i++) {
      imageview imageview = new imageview(this);
      imageview.setbackgroundresource(ids[i]);
      mview.addview(imageview);
    }
    mlayout.addview(mview);
    // 随便添加一个view
    view view = getlayoutinflater().inflate(r.layout.activity_progressview, null);
    mview.addview(view, 3);
    for (int i = 0; i < mview.getchildcount(); i++) {
      radiobutton radiobutton = new radiobutton(this);
      // 设置id的编号
      radiobutton.setid(i);
      mgroup.setorientation(linearlayout.horizontal);
      mgroup.addview(radiobutton);
      if (i == 0) {
        radiobutton.setchecked(true);
      }
    }
    mgroup.setoncheckedchangelistener(this);
    mview.setonchangelistener(this);
  }
  @override
  public void oncheckedchanged(radiogroup group, int checkedid) {
    mview.move2dest(checkedid);
  }
  @override
  public void move2dest(int curid) {
    radiobutton radiobutton = (radiobutton) mgroup.getchildat(curid);
    radiobutton.setchecked(true);
  }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical" >
  <radiogroup
    android:id="@+id/radiogroup"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >
  </radiogroup>
  <linearlayout
    android:id="@+id/body_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
  </linearlayout>
</linearlayout>

更多关于android相关内容感兴趣的读者可查看本站专题:《android基本组件用法总结》、《android开发入门与进阶教程》、《android布局layout技巧总结》、《android视图view技巧总结》、《android编程之activity操作技巧总结》、《android资源操作技巧汇总》及《android控件用法总结

希望本文所述对大家android程序设计有所帮助。