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

Android自定义viewgroup 使用adapter适配数据(6)

程序员文章站 2024-02-24 09:32:37
在自定义viewgroup(5):的基础上,添加使用adapter来适配数据,这样更加的方便,这里只是使用adapter适配数据,不能更新。 package co...

在自定义viewgroup(5):的基础上,添加使用adapter来适配数据,这样更加的方便,这里只是使用adapter适配数据,不能更新。

package com.example.libingyuan.horizontallistview.scrollviewgroup;

import android.content.context;
import android.util.attributeset;
import android.util.displaymetrics;
import android.util.log;
import android.view.gesturedetector;
import android.view.motionevent;
import android.view.view;
import android.view.viewgroup;
import android.view.windowmanager;
import android.widget.baseadapter;
import android.widget.gridview;
import android.widget.scroller;

/**
 * 自定义viewgroup(横向滚动)
 */
public class scrollviewgroup extends viewgroup {
  //滚动计算辅助类
  private scroller mscroller;
  //屏幕宽度
  private int screenwidth;
  //可以移动的最大距离
  private int mmaxdistance;
  //自定义手势监听类
  private scrolltouchlisener mtouchlisener;
  //手势监听
  private gesturedetector mdetector;

  private baseadapter madapter;

  /**
   * 使用new关键字创建对象的时候调用
   */
  public scrollviewgroup(context context) {
    this(context, null);
  }

  /**
   * 在xml文件中使用的时候调用
   */
  public scrollviewgroup(context context, attributeset attrs) {
    this(context, attrs, 0);
  }

  /**
   * 在xml文件中调用,并且使用了自定义属性的时候调用
   */
  public scrollviewgroup(context context, attributeset attrs, int defstyleattr) {
    super(context, attrs, defstyleattr);
    init(context);
  }

  /**
   * 初始化方法
   * 初始化滚动辅助类scroller以及计算出屏幕宽度
   */
  private void init(context context) {
    //初始化辅助类
    mscroller = new scroller(context);
    //获取屏幕宽度
    windowmanager manager = (windowmanager) context
        .getsystemservice(context.window_service);
    displaymetrics outmetrics = new displaymetrics();
    manager.getdefaultdisplay().getmetrics(outmetrics);
    screenwidth = outmetrics.widthpixels;
    //手势指示器初始化
    mtouchlisener = new scrolltouchlisener();
    mdetector = new gesturedetector(context, mtouchlisener);
  }

  /**
   * 滚动时需要重写的方法,用于控制滚动
   */
  @override
  public void computescroll() {
    //判断滚动时候停止
    if (mscroller.computescrolloffset()) {
      //滚动到指定的位置
      scrollto(mscroller.getcurrx(), mscroller.getcurry());
      //这句话必须写,否则不能实时刷新
      invalidate();
    }
  }

  /**
   * 手指触屏事件监听
   */
  @override
  public boolean ontouchevent(motionevent event) {
    mdetector.ontouchevent(event);
    if (event.getaction() == motionevent.action_up) {
      this.onup(event);
    }
    return true;
  }


  public void setadapter(baseadapter adapter) {
    this.madapter = adapter;
    requestlayout();
  }

  /*
   *测量方法,测量父布局的宽度和高度
   */
  @override
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
    removeallviews();
    for (int i = 0; i < madapter.getcount(); i++) {
      view child = madapter.getview(i, null, null);
      addview(child);
    }
    //重新设置宽高
    this.setmeasureddimension(measurewidth(widthmeasurespec, heightmeasurespec), measureheight(widthmeasurespec, heightmeasurespec));
  }

  /**
   * 测量宽度
   */
  private int measurewidth(int widthmeasurespec, int heightmeasurespec) {
    // 宽度
    int sizewidth = measurespec.getsize(widthmeasurespec);
    int modewidth = measurespec.getmode(widthmeasurespec);
    //父控件的宽(wrap_content)
    int width = 0;
    int childcount = getchildcount();

    //重新测量子view的宽度,以及最大高度
    for (int i = 0; i < childcount; i++) {
      view child = getchildat(i);
      measurechild(child, widthmeasurespec, heightmeasurespec);
      // layoutparams lp = child.getlayoutparams();
      /* marginlayoutparams lp = (marginlayoutparams) child.getlayoutparams();
      int childwidth = child.getmeasuredwidth() + lp.leftmargin + lp.rightmargin;
      width += childwidth;*/
      width += child.getmeasuredwidth();
    }
    return modewidth == measurespec.exactly ? sizewidth : width;
  }


  /**
   * 测量高度
   */
  private int measureheight(int widthmeasurespec, int heightmeasurespec) {
    //高度
    int sizeheight = measurespec.getsize(heightmeasurespec);
    int modeheight = measurespec.getmode(heightmeasurespec);
    //父控件的高(wrap_content)
    int height = 0;
    int childcount = getchildcount();

    //重新测量子view的宽度,以及最大高度
    for (int i = 0; i < childcount; i++) {
      view child = getchildat(i);
      measurechild(child, widthmeasurespec, heightmeasurespec);
      /* marginlayoutparams lp = (marginlayoutparams) child.getlayoutparams();
      int childheight = child.getmeasuredheight() + lp.topmargin + lp.bottommargin;
      height += childheight;*/
      height += child.getmeasuredheight();
    }
    height = height / childcount;
    return modeheight == measurespec.exactly ? sizeheight : height;
  }

  /**
   * 给子布局设定位置
   */
  @override
  protected void onlayout(boolean changed, int l, int t, int r, int b) {
    int childleft = 0;//子view左边的间距
    int childwidth;//子view的宽度
    int height = getheight();//屏幕的宽度
    int childcount = getchildcount();//子view的数量
    for (int i = 0; i < childcount; i++) {
      view child = getchildat(i);
     /*  marginlayoutparams lp = (marginlayoutparams) child.getlayoutparams();
      childwidth = child.getmeasuredwidth() + lp.leftmargin + lp.rightmargin;*/
      childwidth = child.getmeasuredwidth();
      child.layout(childleft, 0, childleft + childwidth, height);
      childlayout(child);
      childleft += childwidth;
    }
  }

  /**
   *让子view的子view和子view大小一样
   */
  private void childlayout(view child){
    if (child==null){
      throw new illegalstateexception("scrollviewgroup must has one child");
    }
    if (child instanceof viewgroup){
      if(((viewgroup)child).getchildcount()>0)
        throw new illegalstateexception("view can host only one direct child");
      ((viewgroup) child).getchildat(0).layout(0,0,child.getwidth(),child.getheight());
    }

  }
  @override
  public layoutparams generatelayoutparams(attributeset attrs) {
    return new marginlayoutparams(getcontext(), attrs);
  }

  /*
   *按下事件 action_down
   */
  public boolean ondown(motionevent e) {
    //得到最后一个子view
    view lastchild = getchildat(getchildcount() - 1);
    //获取滑动的最大滑动距离(最后一个child的右边框的坐标减去屏幕的宽度)
    int finalychild = (int) (lastchild.getx() + lastchild.getwidth() - screenwidth);
    mmaxdistance = finalychild;
    //如果停止滚动则取消动画(即手指按下就停止滚动)
    if (!mscroller.isfinished()) {
      mscroller.abortanimation();
    }
    return false;
  }

  /*
  *抬起事件 action_up
  */
  public boolean onup(motionevent e) {
    //如果滑动的距离小于第一个控件的最左边(0)则回弹至(0,0)点
    if (getscrollx() <= 0) {
      scrollto(0, 0);
    }
    //如果滑动的距离大于最大可滑动距离则滑动到最后一个子view
    if (getscrollx() >= mmaxdistance) {
      scrollto(mmaxdistance, 0);
    }
    //刷新界面
    invalidate();
    return false;
  }

  /*
   *action_down 、短按不移动
   */
  public void onshowpress(motionevent e) {
  }

  /*
   *短按action_down、action_up
   */
  public boolean onsingletapup(motionevent e) {
    return false;
  }

  /*
   *action_down 、慢滑动
   */
  public boolean onscroll(motionevent e1, motionevent e2, float distancex, float distancey) {
    //滚动
    scrollby((int) distancex, 0);
    return false;
  }

  // action_down 、长按不滑动
  public void onlongpress(motionevent e) {
  }

  /*
   *action_down 、快滑动、 action_up
   */
  public boolean onfling(motionevent e1, motionevent e2, float velocityx, float velocityy) {
    mscroller.fling(getscrollx(), 0, (int) -velocityx, 0, 0, mmaxdistance, 0, 0);
    return false;
  }

  /**
   * 自定义手势监听类
   */
  private class scrolltouchlisener implements gesturedetector.ongesturelistener {

    //按下事件
    @override
    public boolean ondown(motionevent e) {
      return scrollviewgroup.this.ondown(e);
    }

    //单击事件
    @override
    public void onshowpress(motionevent e) {
      scrollviewgroup.this.onshowpress(e);
    }

    //手指抬起事件
    @override
    public boolean onsingletapup(motionevent e) {
      return scrollviewgroup.this.onsingletapup(e);
    }

    //滚动事件
    @override
    public boolean onscroll(motionevent e1, motionevent e2, float distancex, float distancey) {
      return scrollviewgroup.this.onscroll(e1, e2, distancex, distancey);
    }

    //长按事件
    @override
    public void onlongpress(motionevent e) {
      scrollviewgroup.this.onlongpress(e);
    }

    //滑动事件
    @override
    public boolean onfling(motionevent e1, motionevent e2, float velocityx, float velocityy) {
      return scrollviewgroup.this.onfling(e1, e2, velocityx, velocityy);
    }
  }

}

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