问题
I want to show progress bar around knob. After following this tutorial I created this
knob it is working fine.But How could i modify the above knob to look like the second image
Running code for the first knob is written below.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.View.MeasureSpec;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.RelativeLayout;
public class RoundKnobButton extends RelativeLayout implements
OnGestureListener
{
public int eventValue=10;
//doctory starts
Paint p1,p2,p3;
RectF oval;
int width;
//doctory ends
private GestureDetector gestureDetector;
private float mAngleDown, mAngleUp;
private ImageView ivRotor;
private Bitmap bmpRotorOn, bmpRotorOff;
private boolean mState = false;
private int m_nWidth = 0, m_nHeight = 0;
public interface RoundKnobButtonListener
{
public void onStateChange(boolean newstate);
public void onRotate(int percentage);
}
private RoundKnobButtonListener m_listener;
public void SetListener(RoundKnobButtonListener l)
{
m_listener = l;
}
public void SetState(boolean state)
{
mState = state;
ivRotor.setImageBitmap(state ? bmpRotorOn : bmpRotorOff);
}
public RoundKnobButton(Context context, int back, int rotoron,
int rotoroff, final int w, final int h) {
super(context);
//doctory starts
width = w;
p1 = new Paint(1);
p1.setColor(Color.rgb(86, 86, 86));
p1.setStyle(android.graphics.Paint.Style.FILL);
p2 = new Paint(1);
p2.setColor(Color.rgb(245, 109, 89));
p2.setStyle(android.graphics.Paint.Style.FILL);
p3 = new Paint(1);
p3.setColor(Color.GREEN);
p3.setStyle(android.graphics.Paint.Style.STROKE);
oval = new RectF();
//doctory ends...
// we won't wait for our size to be calculated, we'll just store out
// fixed size
m_nWidth = w;
m_nHeight = h;
// create stator
ImageView ivBack = new ImageView(context);
ivBack.setImageResource(back);
RelativeLayout.LayoutParams lp_ivBack = new RelativeLayout.LayoutParams(
w, h);
lp_ivBack.addRule(RelativeLayout.CENTER_IN_PARENT);
addView(ivBack, lp_ivBack);
// load rotor images
Bitmap srcon = BitmapFactory.decodeResource(context.getResources(),
rotoron);
Bitmap srcoff = BitmapFactory.decodeResource(context.getResources(),
rotoroff);
float scaleWidth = ((float) w) / srcon.getWidth();
float scaleHeight = ((float) h) / srcon.getHeight();
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
bmpRotorOn = Bitmap.createBitmap(srcon, 0, 0, srcon.getWidth(),
srcon.getHeight(), matrix, true);
bmpRotorOff = Bitmap.createBitmap(srcoff, 0, 0, srcoff.getWidth(),
srcoff.getHeight(), matrix, true);
// create rotor
ivRotor = new ImageView(context);
ivRotor.setImageBitmap(bmpRotorOn);
RelativeLayout.LayoutParams lp_ivKnob = new RelativeLayout.LayoutParams(
w, h);// LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp_ivKnob.addRule(RelativeLayout.CENTER_IN_PARENT);
addView(ivRotor, lp_ivKnob);
// set initial state
SetState(mState);
// enable gesture detector
gestureDetector = new GestureDetector(getContext(), this);
}
/**
* math..
*
* @param x
* @param y
* @return
*/
private float cartesianToPolar(float x, float y) {
return (float) -Math.toDegrees(Math.atan2(x - 0.5f, y - 0.5f));
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event))
return true;
else
return super.onTouchEvent(event);
}
public boolean onDown(MotionEvent event)
{
float x = event.getX() / ((float) getWidth());
float y = event.getY() / ((float) getHeight());
mAngleDown = cartesianToPolar(1 - x, 1 - y);// 1- to correct our custom
// axis direction
return true;
}
public boolean onSingleTapUp(MotionEvent e)
{
float x = e.getX() / ((float) getWidth());
float y = e.getY() / ((float) getHeight());
mAngleUp = cartesianToPolar(1 - x, 1 - y);// 1- to correct our custom
// axis direction
// if we click up the same place where we clicked down, it's just a
// button press
if (!Float.isNaN(mAngleDown) && !Float.isNaN(mAngleUp)
&& Math.abs(mAngleUp - mAngleDown) < 10) {
SetState(!mState);
if (m_listener != null)
m_listener.onStateChange(mState);
}
return true;
}
public void setRotorPosAngle(float deg)
{
if (deg >= 210 || deg <= 150)
{
if (deg > 180)
deg = deg - 360;
Matrix matrix = new Matrix();
ivRotor.setScaleType(ScaleType.MATRIX);
// matrix.postRotate((float) deg, 210 / 2, 210 / 2);// getWidth()/2,
// getHeight()/2);
matrix.postRotate((float) deg, m_nWidth/2, m_nHeight/2);//getWidth()/2, getHeight()/2);
ivRotor.setImageMatrix(matrix);
}
}
public void setRotorPercentage(int percentage)
{
int posDegree = percentage * 3 - 150;
if (posDegree < 0)
posDegree = 360 + posDegree;
setRotorPosAngle(posDegree);
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
float x = e2.getX() / ((float) getWidth());
float y = e2.getY() / ((float) getHeight());
float rotDegrees = cartesianToPolar(1 - x, 1 - y);// 1- to correct our
// custom axis
// direction
if (!Float.isNaN(rotDegrees)) {
// instead of getting 0-> 180, -180 0 , we go for 0 -> 360
float posDegrees = rotDegrees;
if (rotDegrees < 0)
posDegrees = 360 + rotDegrees;
// deny full rotation, start start and stop point, and get a linear
// scale
if (posDegrees > 210 || posDegrees < 150) {
// rotate our imageview
setRotorPosAngle(posDegrees);
// get a linear scale
float scaleDegrees = rotDegrees + 150; // given the current
// parameters, we go
// from 0 to 300
// get position percent
int percent = (int) (scaleDegrees / 3);
if (m_listener != null)
m_listener.onRotate(percent);
return true; // consumed
} else
return false;
} else
return false; // not consumed
}
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2,
float arg3) {
return false;
}
public void onLongPress(MotionEvent e) {
}
/*@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
int i = width / 4;
oval.set(i - i / 2, i / 2, i * 3 + i / 2, i * 3 + i / 2);
canvas.drawOval(oval, p1);
canvas.drawArc(oval, -90F, (int)Math.round((360D * Double.valueOf(eventValue).doubleValue()) / 100D), true, p2);
canvas.drawLine(20, 30, 120, 200, p2);
}*/
/*@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int desiredWidth = width;
int desiredHeight = width;
int widthMode = android.view.View.MeasureSpec.getMode(widthMeasureSpec);
int widthSize = android.view.View.MeasureSpec.getSize(widthMeasureSpec);
int heightMode = android.view.View.MeasureSpec.getMode(heightMeasureSpec);
int heightSize = android.view.View.MeasureSpec.getSize(heightMeasureSpec);
int measuredWidth;
int measuredHeight;
if (widthMode == MeasureSpec.EXACTLY)
{
measuredWidth = widthSize ;
}
else if (widthMode == MeasureSpec.AT_MOST)
{
measuredWidth = Math.min(desiredWidth , widthSize);
}
else
{
measuredWidth = desiredWidth;
}
if (heightMode == MeasureSpec.EXACTLY)
{
measuredHeight = heightSize ;
}
else if (heightMode == MeasureSpec.AT_MOST)
{
measuredHeight = Math.min(desiredHeight, heightSize );
}
else
{
measuredHeight = desiredHeight;
}
setMeasuredDimension(measuredWidth, measuredHeight);
}
*/
}
I have created onDraw and onMeasure function function and try to draw outer progress, or how could i modify it.
Edit
Is it possible to change the rotation percentage to 20 . I mean it shows progress form 0 to 99. is it possible to convert it to 0 to 12.
回答1:
Use two XML files.
circular_progress_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="270"
android:toDegrees="270">
<shape
android:innerRadiusRatio="2.5"
android:shape="ring"
android:thickness="1dp">
<gradient
android:angle="0"
android:endColor="#22FA05"
android:startColor="#22FA05"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
and background_circle.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadiusRatio="2.5"
android:thickness="1dp"
android:useLevel="false">
<solid android:color="#000000" />
</shape>
and finally
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="250dp"
android:layout_height="250dp"
android:indeterminate="false"
android:progressDrawable="@drawable/circular_progress_drawable"
android:background="@drawable/background_circle"
style="?android:attr/progressBarStyleHorizontal"
android:max="100"
android:progress="25" />
Note that set width and height based on the image position you have
来源:https://stackoverflow.com/questions/27700637/custom-knob-view-for-controlling-volume