Android自定义垂直拖动seekbar进度条
程序员文章站
2023-12-05 22:20:22
android自带的seekbar是水平的,要垂直的,必须自己写一个类,继承seekbar。
一个简单的垂直seekbar的例子:
(但是它其实是存在一些问题的。不过要...
android自带的seekbar是水平的,要垂直的,必须自己写一个类,继承seekbar。
一个简单的垂直seekbar的例子:
(但是它其实是存在一些问题的。不过要是满足基本需要还是可以凑合的)
package com.example.helloverticalseekbar; import android.content.context; import android.graphics.canvas; import android.util.attributeset; import android.view.motionevent; import android.widget.seekbar; public class verticalseekbar extends seekbar { public verticalseekbar(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); } public verticalseekbar(context context, attributeset attrs) { super(context, attrs); } public verticalseekbar(context context) { super(context); } @override protected void onsizechanged(int w, int h, int oldw, int oldh) { super.onsizechanged(h, w, oldh, oldw); } @override protected synchronized void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(heightmeasurespec, widthmeasurespec); setmeasureddimension(getmeasuredheight(), getmeasuredwidth()); } @override protected synchronized void ondraw(canvas canvas) { canvas.rotate(-90); canvas.translate(-getheight(), 0); super.ondraw(canvas); } @override public boolean ontouchevent(motionevent event) { if (!isenabled()) { return false; } switch (event.getaction()) { case motionevent.action_down: case motionevent.action_move: case motionevent.action_up: setprogress(getmax() - (int) (getmax() * event.gety() / getheight())); onsizechanged(getwidth(), getheight(), 0, 0); break; case motionevent.action_cancel: break; } return true; } }
demo中加上一个水平seekbar作为对比,代码如下:
activity:
helloseekbaractivity
package com.example.helloverticalseekbar; import android.os.bundle; import android.app.activity; import android.util.log; import android.view.menu; import android.widget.seekbar; import android.widget.textview; import android.widget.seekbar.onseekbarchangelistener; public class helloseekbaractivity extends activity { private seekbar horiseekbar = null; private textview horitext = null; private verticalseekbar verticalseekbar = null; private textview verticaltext = null; @override protected void oncreate(bundle savedinstancestate) { log.d(appconstants.log_tag, "oncreate"); super.oncreate(savedinstancestate); setcontentview(r.layout.activity_hello_seek_bar); horiseekbar = (seekbar) findviewbyid(r.id.horiseekbar); horitext = (textview)findviewbyid(r.id.horitext); horiseekbar.setonseekbarchangelistener(horiseekbarlistener); verticalseekbar = (verticalseekbar)findviewbyid(r.id.verticalseekbar); verticaltext = (textview)findviewbyid(r.id.verticaltext); verticalseekbar.setonseekbarchangelistener(verticalseekbarchangelistener); } @override public boolean oncreateoptionsmenu(menu menu) { getmenuinflater().inflate(r.menu.hello_seek_bar, menu); return true; } private onseekbarchangelistener horiseekbarlistener = new onseekbarchangelistener() { @override public void onstoptrackingtouch(seekbar seekbar) { } @override public void onstarttrackingtouch(seekbar seekbar) { } @override public void onprogresschanged(seekbar seekbar, int progress, boolean fromuser) { log.d(appconstants.log_tag, "horizontal seekbar --> onprogresschanged"); horitext.settext(integer.tostring(progress)); } }; private onseekbarchangelistener verticalseekbarchangelistener = new onseekbarchangelistener() { @override public void onstoptrackingtouch(seekbar seekbar) { } @override public void onstarttrackingtouch(seekbar seekbar) { } @override public void onprogresschanged(seekbar seekbar, int progress, boolean fromuser) { log.d(appconstants.log_tag, "vertical seekbar --> onprogresschanged"); verticaltext.settext(integer.tostring(progress)); } }; }
布局:
activity_hello_seek_bar.xml
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingbottom="@dimen/activity_vertical_margin" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" tools:context=".helloseekbaractivity" > <textview android:id="@+id/mytextview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparenttop="true" android:text="@string/hello_world" /> <seekbar android:id="@+id/horiseekbar" android:layout_width="match_parent" android:layout_height="20dp" android:layout_below="@id/mytextview" /> <textview android:id="@+id/horitext" android:layout_width="wrap_content" android:layout_height="20dp" android:layout_below="@id/horiseekbar" android:text="horizontal" /> <com.example.helloverticalseekbar.verticalseekbar android:id="@+id/verticalseekbar" android:layout_width="wrap_content" android:layout_height="200dp" android:layout_below="@id/horitext" /> <textview android:id="@+id/verticaltext" android:layout_width="wrap_content" android:layout_height="20dp" android:layout_below="@id/verticalseekbar" android:text="vertical" /> </relativelayout>
运行截图:
一个改进版的seekbar
package com.example.helloverticalseekbarv2; import android.content.context; import android.graphics.canvas; import android.graphics.rect; import android.graphics.drawable.drawable; import android.util.attributeset; import android.view.motionevent; import android.view.view; import android.view.viewconfiguration; import android.view.viewgroup; import android.view.viewparent; import android.widget.seekbar; public class verticalseekbar extends seekbar { private boolean misdragging; private float mtouchdowny; private int mscaledtouchslop; private boolean isinscrollingcontainer = false; public boolean isinscrollingcontainer() { return isinscrollingcontainer; } public void setinscrollingcontainer(boolean isinscrollingcontainer) { this.isinscrollingcontainer = isinscrollingcontainer; } /** * on touch, this offset plus the scaled value from the position of the * touch will form the progress value. usually 0. */ float mtouchprogressoffset; public verticalseekbar(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); mscaledtouchslop = viewconfiguration.get(context).getscaledtouchslop(); } public verticalseekbar(context context, attributeset attrs) { super(context, attrs); } public verticalseekbar(context context) { super(context); } @override protected void onsizechanged(int w, int h, int oldw, int oldh) { super.onsizechanged(h, w, oldh, oldw); } @override protected synchronized void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(heightmeasurespec, widthmeasurespec); setmeasureddimension(getmeasuredheight(), getmeasuredwidth()); } @override protected synchronized void ondraw(canvas canvas) { canvas.rotate(-90); canvas.translate(-getheight(), 0); super.ondraw(canvas); } @override public boolean ontouchevent(motionevent event) { if (!isenabled()) { return false; } switch (event.getaction()) { case motionevent.action_down: if (isinscrollingcontainer()) { mtouchdowny = event.gety(); } else { setpressed(true); invalidate(); onstarttrackingtouch(); tracktouchevent(event); attemptclaimdrag(); onsizechanged(getwidth(), getheight(), 0, 0); } break; case motionevent.action_move: if (misdragging) { tracktouchevent(event); } else { final float y = event.gety(); if (math.abs(y - mtouchdowny) > mscaledtouchslop) { setpressed(true); invalidate(); onstarttrackingtouch(); tracktouchevent(event); attemptclaimdrag(); } } onsizechanged(getwidth(), getheight(), 0, 0); break; case motionevent.action_up: if (misdragging) { tracktouchevent(event); onstoptrackingtouch(); setpressed(false); } else { // touch up when we never crossed the touch slop threshold // should // be interpreted as a tap-seek to that location. onstarttrackingtouch(); tracktouchevent(event); onstoptrackingtouch(); } onsizechanged(getwidth(), getheight(), 0, 0); // progressbar doesn't know to repaint the thumb drawable // in its inactive state when the touch stops (because the // value has not apparently changed) invalidate(); break; } return true; } private void tracktouchevent(motionevent event) { final int height = getheight(); final int top = getpaddingtop(); final int bottom = getpaddingbottom(); final int available = height - top - bottom; int y = (int) event.gety(); float scale; float progress = 0; // 下面是最小值 if (y > height - bottom) { scale = 0.0f; } else if (y < top) { scale = 1.0f; } else { scale = (float) (available - y + top) / (float) available; progress = mtouchprogressoffset; } final int max = getmax(); progress += scale * max; setprogress((int) progress); } /** * this is called when the user has started touching this widget. */ void onstarttrackingtouch() { misdragging = true; } /** * this is called when the user either releases his touch or the touch is * canceled. */ void onstoptrackingtouch() { misdragging = false; } private void attemptclaimdrag() { viewparent p = getparent(); if (p != null) { p.requestdisallowintercepttouchevent(true); } } @override public synchronized void setprogress(int progress) { super.setprogress(progress); onsizechanged(getwidth(), getheight(), 0, 0); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。