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

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>

运行截图:

Android自定义垂直拖动seekbar进度条

一个改进版的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);

 }

}

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