Android自定义滚动选择器实例代码
程序员文章站
2024-02-23 10:55:40
android自定义滚动选择器
实现图片的效果
代码如下
package com.linzihui.widget;
import a...
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(); } };
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。