软件编程
位置:首页>> 软件编程>> Android编程>> Android自定义垂直拖动seekbar进度条

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

作者:圣骑士wind  发布时间:2023-03-21 13:19:02 

标签:Android,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);

}

}

来源:http://www.cnblogs.com/Sharley/p/7772151.html

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com