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

Android自定义滚动选择器实例代码

程序员文章站 2024-02-19 19:06:40
android自定义滚动选择器 实现图片的效果 代码如下 package com.linzihui.widget; import a...

android自定义滚动选择器

实现图片的效果

Android自定义滚动选择器实例代码

代码如下

package com.linzihui.widget;

import android.annotation.suppresslint;
import android.content.context;
import android.graphics.canvas;
import android.graphics.paint;
import android.graphics.paint.align;
import android.graphics.paint.fontmetricsint;
import android.graphics.paint.style;
import android.os.handler;
import android.os.message;
import android.util.attributeset;
import android.view.motionevent;
import android.view.view;


import java.util.arraylist;
import java.util.list;
import java.util.timer;
import java.util.timertask;

/**
 * 自定义滚动选择器
 * 
 * @author cuiran
 *
 */
@suppresslint({ "handlerleak", "clickableviewaccessibility" })
public class pickerscrollview extends view {

  public static final string tag = "pickerview";
  /**
   * text之间间距和mintextsize之比
   */
  public static final float margin_alpha = 2.8f;
  /**
   * 自动回滚到中间的速度
   */
  public static final float speed = 2;

  private list<pickers> mdatalist;
  /**
   * 选中的位置,这个位置是mdatalist的中心位置,一直不变
   */
  private int mcurrentselected;
  private paint mpaint;

  private float mmaxtextsize = 20;
  private float mmintextsize = 10;

  private float mmaxtextalpha = 255;
  private float mmintextalpha = 120;

  private int mcolortext = 0x333333;

  private int mviewheight;
  private int mviewwidth;

  private float mlastdowny;
  /**
   * 滑动的距离
   */
  private float mmovelen = 0;
  private boolean isinit = false;
  private onselectlistener mselectlistener;
  private timer timer;
  private mytimertask mtask;

  handler updatehandler = new handler() {

    @override
    public void handlemessage(message msg) {
      if (math.abs(mmovelen) < speed) {
        mmovelen = 0;
        if (mtask != null) {
          mtask.cancel();
          mtask = null;
          performselect();
        }
      } else
        // 这里mmovelen / math.abs(mmovelen)是为了保有mmovelen的正负号,以实现上滚或下滚
        mmovelen = mmovelen - mmovelen / math.abs(mmovelen) * speed;
      invalidate();
    }

  };

  public pickerscrollview(context context) {
    super(context);
    init();
  }

  public pickerscrollview(context context, attributeset attrs) {
    super(context, attrs);
    init();
  }

  public void setonselectlistener(onselectlistener listener) {
    mselectlistener = listener;
  }

  private void performselect() {
    if (mselectlistener != null)
      mselectlistener.onselect(mdatalist.get(mcurrentselected));
  }

  public void setdata(list<pickers> datas) {
    mdatalist = datas;
    mcurrentselected = datas.size() / 2;
    invalidate();
  }

  /**
   * 选择选中的item的index
   * 
   * @param selected
   */
  public void setselected(int selected) {
    mcurrentselected = selected;
    int distance = mdatalist.size() / 2 - mcurrentselected;
    if (distance < 0)
      for (int i = 0; i < -distance; i++) {
        moveheadtotail();
        mcurrentselected--;
      }
    else if (distance > 0)
      for (int i = 0; i < distance; i++) {
        movetailtohead();
        mcurrentselected++;
      }
    invalidate();
  }

  /**
   * 选择选中的内容
   * 
   * @param mselectitem
   */
  public void setselected(string mselectitem) {
    for (int i = 0; i < mdatalist.size(); i++)
      if (mdatalist.get(i).equals(mselectitem)) {
        setselected(i);
        break;
      }
  }

  private void moveheadtotail() {
    pickers head = mdatalist.get(0);
    mdatalist.remove(0);
    mdatalist.add(head);
  }

  private void movetailtohead() {
    pickers tail = mdatalist.get(mdatalist.size() - 1);
    mdatalist.remove(mdatalist.size() - 1);
    mdatalist.add(0, tail);
  }

  @override
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
    super.onmeasure(widthmeasurespec, heightmeasurespec);
    mviewheight = getmeasuredheight();
    mviewwidth = getmeasuredwidth();
    // 按照view的高度计算字体大小
    mmaxtextsize = mviewheight / 8.0f;
    mmintextsize = mmaxtextsize / 2f;
    isinit = true;
    invalidate();
  }

  private void init() {
    timer = new timer();
    mdatalist = new arraylist<pickers>();
    mpaint = new paint(paint.anti_alias_flag);
    mpaint.setstyle(style.fill);
    mpaint.settextalign(align.center);
    mpaint.setcolor(mcolortext);
  }

  @override
  protected void ondraw(canvas canvas) {
    super.ondraw(canvas);
    // 根据index绘制view
    if (isinit)
      drawdata(canvas);
  }

  private void drawdata(canvas canvas) {
    // 先绘制选中的text再往上往下绘制其余的text
    float scale = parabola(mviewheight / 4.0f, mmovelen);
    float size = (mmaxtextsize - mmintextsize) * scale + mmintextsize;
    mpaint.settextsize(size);
    mpaint.setalpha((int) ((mmaxtextalpha - mmintextalpha) * scale + mmintextalpha));
    // text居中绘制,注意baseline的计算才能达到居中,y值是text中心坐标
    float x = (float) (mviewwidth / 2.0);
    float y = (float) (mviewheight / 2.0 + mmovelen);
    fontmetricsint fmi = mpaint.getfontmetricsint();
    float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));

    int indexs = mcurrentselected;
    string textdata = mdatalist.get(indexs).getshowconetnt();
    canvas.drawtext(textdata, x, baseline, mpaint);

    // 绘制上方data
    for (int i = 1; (mcurrentselected - i) >= 0; i++) {
      drawothertext(canvas, i, -1);
    }
    // 绘制下方data
    for (int i = 1; (mcurrentselected + i) < mdatalist.size(); i++) {
      drawothertext(canvas, i, 1);
    }
  }

  /**
   * @param canvas
   * @param position
   *      距离mcurrentselected的差值
   * @param type
   *      1表示向下绘制,-1表示向上绘制
   */
  private void drawothertext(canvas canvas, int position, int type) {
    float d = (float) (margin_alpha * mmintextsize * position + type
        * mmovelen);
    float scale = parabola(mviewheight / 4.0f, d);
    float size = (mmaxtextsize - mmintextsize) * scale + mmintextsize;
    mpaint.settextsize(size);
    mpaint.setalpha((int) ((mmaxtextalpha - mmintextalpha) * scale + mmintextalpha));
    float y = (float) (mviewheight / 2.0 + type * d);
    fontmetricsint fmi = mpaint.getfontmetricsint();
    float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));

    int indexs = mcurrentselected + type * position;
    string textdata = mdatalist.get(indexs).getshowconetnt();
    canvas.drawtext(textdata, (float) (mviewwidth / 2.0), baseline, mpaint);
  }

  /**
   * 抛物线
   * 
   * @param zero
   *      零点坐标
   * @param x
   *      偏移量
   * @return scale
   */
  private float parabola(float zero, float x) {
    float f = (float) (1 - math.pow(x / zero, 2));
    return f < 0 ? 0 : f;
  }

  @override
  public boolean ontouchevent(motionevent event) {
    switch (event.getactionmasked()) {
    case motionevent.action_down:
      dodown(event);
      break;
    case motionevent.action_move:
      domove(event);
      break;
    case motionevent.action_up:
      doup(event);
      break;
    }
    return true;
  }

  private void dodown(motionevent event) {
    if (mtask != null) {
      mtask.cancel();
      mtask = null;
    }
    mlastdowny = event.gety();
  }

  private void domove(motionevent event) {

    mmovelen += (event.gety() - mlastdowny);

    if (mmovelen > margin_alpha * mmintextsize / 2) {
      // 往下滑超过离开距离
      movetailtohead();
      mmovelen = mmovelen - margin_alpha * mmintextsize;
    } else if (mmovelen < -margin_alpha * mmintextsize / 2) {
      // 往上滑超过离开距离
      moveheadtotail();
      mmovelen = mmovelen + margin_alpha * mmintextsize;
    }

    mlastdowny = event.gety();
    invalidate();
  }

  private void doup(motionevent event) {
    // 抬起手后mcurrentselected的位置由当前位置move到中间选中位置
    if (math.abs(mmovelen) < 0.0001) {
      mmovelen = 0;
      return;
    }
    if (mtask != null) {
      mtask.cancel();
      mtask = null;
    }
    mtask = new mytimertask(updatehandler);
    timer.schedule(mtask, 0, 10);
  }

  class mytimertask extends timertask {
    handler handler;

    public mytimertask(handler handler) {
      this.handler = handler;
    }

    @override
    public void run() {
      handler.sendmessage(handler.obtainmessage());
    }

  }

  public interface onselectlistener {
    void onselect(pickers pickers);
  }
}

package com.linzihui.widget;

import java.io.serializable;

public class pickers implements serializable {

  private static final long serialversionuid = 1l;

  private string showconetnt;
  private string showid;

  public string getshowconetnt() {
    return showconetnt;
  }

  public string getshowid() {
    return showid;
  }

  public pickers(string showconetnt, string showid) {
    super();
    this.showconetnt = showconetnt;
    this.showid = showid;
  }

  public pickers() {
    super();
  }

}

使用的时候 新建一个activity 里面对view进行处理

 pickerscrlllview=(pickerscrollview)findviewbyid(r.id.pickerscrlllview);
    pickerscrlllview.setonselectlistener(pickerlistener);

 pickerscrollview.onselectlistener pickerlistener0 = new pickerscrollview.onselectlistener() {

    @override
    public void onselect(pickers pickers) {
      s1=pickers.getshowconetnt();
    }
  };

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

上一篇: map实现按value升序排序

下一篇: