当前位置: 移动技术网 > IT编程>移动开发>Android > Android-自定义控件之ListView下拉刷新的实现

Android-自定义控件之ListView下拉刷新的实现

2019年07月24日  | 移动技术网IT编程  | 我要评论

昆明个人无抵押贷款,电脑报价大全,好看的穿越小说完本推荐

自定义控件学了很久了,发现学了总是忘,于是打算用博客来记录自己学习的知识点。

今天是自定义listview来实现下拉刷新,这些文章都是借鉴慕课网上的视频来写的.

自定义一个控件,先是看它继承于那个控件,如果我们继承view控件的话,那得让我们写很多关于listview的功能,这些东西我自己觉得很麻烦,而且也没有那个必要因为我们可以直接继承listview,在listview的基础上来加一些我们需要的东西。

1.向listview加header布局

  private void initview(context context)
  {
    mlayoutinflater = layoutinflater.from(context);
    mheaerview = mlayoutinflater.inflate(r.layout.header_layout, null, false);
    addheaderview(mheaerview);
  }

2.隐藏header布局

private void initview(context context) {
    mlayoutinflater = layoutinflater.from(context);
    mheaerview = mlayoutinflater.inflate(r.layout.header_layout, null, false);
    measureview(mheaerview);
    mheaderviewheight = mheaerview.getmeasuredheight();
    setheaderviewheightpadding(mheaderviewheight);
    log.i("main", mheaderviewheight + "");
    addheaderview(mheaerview);
  }
  private void measureview(view view)
  {
    viewgroup.layoutparams lp = view.getlayoutparams();
    if(lp == null)
    {
      lp = new viewgroup.layoutparams(viewgroup.layoutparams.match_parent, viewgroup.layoutparams.wrap_content);
    }
    //mheaerview.measure(viewgroup.layoutparams.match_parent, viewgroup.layoutparams.wrap_content);
    /**
     * width 和height里面包含的不仅仅有view的宽和高,还有view控件的测量模式
     * 测量模式的产生方式就是如下所示
     */
    int width = viewgroup.getchildmeasurespec(0,0,lp.width);
    int height = 0;
    int tempheight = lp.height;
    if(tempheight > 0)
    {
      height = measurespec.makemeasurespec(tempheight, measurespec.exactly);
    }
    view.measure(width, height);

  }
  private void setheaderviewheightpadding(int padding) {
    mheaerview.setpadding(mheaerview.getpaddingleft(), -padding, mheaerview.getpaddingright(), mheaerview.getpaddingbottom());
    mheaerview.invalidate();
  }

3.实现listview的下拉刷新(一)

要想实现listview的下拉刷新,必须监听listview是否滑动到最顶端,因此要实现listview的监听接口onscrolllistener,并且要监听listview的ontouch事件。根据滑动的情况来判断刷新的情况。

首先我们在定义了一个成员变量来保存listview的状态--mstate

其次定义了几个静态常量来表示不同的状态  

 private final static int none = 0; // 无状态
  private final static int down_update = 1; // 提示下拉可以刷新
  private final static int update = 2; // 提示松开可以刷新
  private final static int reflash = 3; // 更新

最后则是根据不同的滑动来更改mstate的状态

@override
  public boolean ontouchevent(motionevent ev) {

    switch (ev.getaction()) {
      case motionevent.action_down: {
        if (mfirstvisibleitem == 0) {
          misremark = true; // misremark只是一个标记,表示当前可见的第一个item是不是所有的item中的第一个
          mstarty = (int) ev.gety();
          log.i("main", "我进来了");
        }
        break;
      }
      case motionevent.action_move: {
        onmove(ev);
        tempy = (int) (ev.gety() - mstarty);
        log.i("main", "tempy = " + tempy);
        break;
      }
      case motionevent.action_up: {

        if(mstate == down_update)
        {
          mstate = none;
        }
        if(mstate == update)
        {
          mstate = reflash;
          mlistener.reflash();
          log.i("main", "我来了");
        }
        log.i("main", "tempy11 = " + tempy);
        if(tempy <= 0 && misremark)
        {
          log.i("main", "我进来le");
          mstate = none;
        }

        change();
        break;
      }
    }


    return super.ontouchevent(ev);
  }

  private void onmove(motionevent ev) {
    if (misremark) {
      if (ev.gety() - mstarty > 0) {
        int dy = (int) (ev.gety() - mstarty);
        if (dy > mheaderviewheight + 20) {
          mstate = update;
        } else {
          mstate = down_update;
        }
        setheaderviewheightpadding(mheaderviewheight - dy);
        change();
      }
      return;
    }
    return;
  }
/**
 *change方法主要是用来处理不同状态下的事件
 *
 */
  private void change() {
    initchildview();
    rotateanimation ani = new rotateanimation(0, 180, rotateanimation.relative_to_self, 0.5f, rotateanimation.relative_to_self, 0.5f);
    ani.setduration(500);
    ani.setfillafter(true);
    rotateanimation ani1 = new rotateanimation(180, 0, rotateanimation.relative_to_self, 0.5f, rotateanimation.relative_to_self, 0.5f);
    ani1.setduration(500);
    ani1.setfillafter(true);
    if (mstate == update)
    {
      mprogressbar.setvisibility(view.gone);
      mimageview.setvisibility(view.visible);
      mimageview.clearanimation();
      mimageview.setanimation(ani);
      mtextviewflash.settext("松开可以刷新!");
      mtextviewtime.setvisibility(view.visible);
      mtextviewtime.settext("上次更新的时间:" + mupdatetime);
    }
    if (mstate == down_update)
    {
      mprogressbar.setvisibility(view.gone);
      mimageview.setvisibility(view.visible);
      mtextviewtime.setvisibility(view.visible);
      mimageview.clearanimation();
      mimageview.setanimation(ani1);
      mtextviewflash.settext("下拉可以刷新");
      mtextviewtime.settext("上次更新的时间:" + mupdatetime);
    }
    if (mstate == reflash)
    {
      setheaderviewheightpadding(10);
      mprogressbar.setvisibility(view.visible);
      mimageview.setvisibility(view.gone);
      mtextviewtime.setvisibility(view.gone);
      mtextviewflash.settext("正在刷新...");
      mimageview.clearanimation();
    }
    if(mstate == none)
    {
      log.i("main", "workspace");
      setheaderviewheightpadding(mheaderviewheight);
      misremark = false;
      mprogressbar.setvisibility(view.gone);
      mimageview.setvisibility(view.visible);
      mimageview.setanimation(ani1);
    }
  }
  private void initchildview()
  {
    if(mtextviewflash == null)
    {
      mtextviewflash = (textview) mheaerview.findviewbyid(r.id.id_textview_flash);
    }
    if(mtextviewtime == null)
    {
      mtextviewtime = (textview) mheaerview.findviewbyid(r.id.id_textview_time);
    }
    if(mimageview == null)
    {
      mimageview = (imageview) mheaerview.findviewbyid(r.id.id_imagview);
    }
    if(mprogressbar == null)
    {
      mprogressbar = (progressbar) mheaerview.findviewbyid(r.id.id_progressbar);
    }
  }

4.实现listview的下拉刷新(二)

 经过上面的过程,是可以下拉的,处理不同状态下的事件。还有一个问题就是刷新,也就是加载新的数据。加载刷新的操作肯定必须在ui线程中,因此listview中必须得有一个回调接口,用来minaactivity来实现,并且来进行一些操作。

  回调接口:

  public void setonflashlistener(flashlistener listener)
  {
    this.mlistener = listener;
  }

  public interface flashlistener
  {
    void reflash();
  }

回调接口的调用:

        if(mstate == update)
        {
          mstate = reflash;
          mlistener.reflash();
          log.i("main", "我来了");
        }

mainactivity中回调接口的实现和接口方法的实现:

mlistview.setonflashlistener(new flashlistview.flashlistener() {
      @override
      public void reflash() {
        handler handler = new handler();
        handler.postdelayed(new runnable() {
          @override
          public void run() {
            adddatas();
            loaddatas();
            mlistview.refalshcomplete();
          }
        }, 5000);
      }
    });


  

 private void adddatas()
  {
    int i = mdatas.size();
    for(int j = i; j < i + 10; j++)
    {
      mdatas.add(new bean("title" + j, "content" + j, r.mipmap.ic_launcher));
    }
    myadapter.datachange(mdatas);
  }
  private void loaddatas()
  {
    mlistview.setadapter(myadapter);
  }

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网