I want to display the labels on pie chart items..please guide me..
Main.java:-
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
PieDetailsItem item;
int maxCount=0;
int itemCount=0;
int items[]={2,6,0};
int colors[]={-6777216,-16776961,-16711681};
String itemslabel[]={" vauesr ur 100"," vauesr ur 200"," vauesr ur 300"};
for(int i=0;i<items.length;i++)
{
itemCount=items[i];
item=new PieDetailsItem();
item.count=itemCount;
item.label=itemslabel[i];
item.color=colors[i];
piedata.add(item);
maxCount=maxCount+itemCount;
}
int size=155;
int BgColor=0xffa11b1;
Bitmap mBaggroundImage=Bitmap.createBitmap(size,size,Bitmap.Config.ARGB_8888);
View_PieChart piechart=new View_PieChart(this);
piechart.setLayoutParams(new LayoutParams(size,size));
piechart.setGeometry(size, size, 2, 2, 2, 2, 2130837504);
piechart.setSkinparams(BgColor);
piechart.setData(piedata, maxCount);
piechart.invalidate();
piechart.draw(new Canvas(mBaggroundImage));
piechart=null;
ImageView mImageView=new ImageView(this);
mImageView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
mImageView.setBackgroundColor(BgColor);
mImageView.setImageBitmap(mBaggroundImage);
LinearLayout finalLayout=(LinearLayout)findViewById(R.id.pie_container);
finalLayout.addView(mImageView);
}
View_piechart.java:-
public View_PieChart(Context context) {
super(context);
Log.w(" single cons ", " single cons");
}
public View_PieChart(Context context, AttributeSet attr) {
super(context, attr);
Log.w(" double cons ", " double cons");
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mState != IS_READY_TO_DRAW) {
return;
}
canvas.drawColor(mBgcolor);
mBagpaints.setAntiAlias(true);
mBagpaints.setStyle(Paint.Style.FILL);
mBagpaints.setColor(0x88FF0000);
mBagpaints.setStrokeWidth(0.0f);
mLinePaints.setAntiAlias(true);
mLinePaints.setColor(0xff000000);
mLinePaints.setStrokeWidth(3.0f);
mLinePaints.setStyle(Paint.Style.STROKE);
RectF mOvals = new RectF(mGapleft, mGapTop, mWidth - mGapright, mHeight
- mGapBottm);
mStart = START_INC;
PieDetailsItem item;
for (int i = 0; i < mdataArray.size(); i++) {
item = (PieDetailsItem) mdataArray.get(i);
mBagpaints.setColor(item.color);
mSweep = (float) 360* ((float) item.count / (float) mMaxConnection);
canvas.drawArc(mOvals, mStart, mSweep, true, mBagpaints);
canvas.drawArc(mOvals, mStart, mSweep, true, mLinePaints);
mStart = mStart + mSweep;
}
mState = IS_DRAW;
}
public void setGeometry(int width, int height, int gapleft, int gapright,
int gaptop, int gapbottom, int overlayid) {
mWidth = width;
mHeight = height;
mGapleft = gapleft;
mGapright = gapright;
mGapBottm = gapbottom;
mGapTop = gaptop;
}
public void setSkinparams(int bgcolor) {
Log.w(" Set bg color : ", bgcolor + "");
mBgcolor = bgcolor;
}
public void setData(List<PieDetailsItem> data, int maxconnection) {
mdataArray = data;
mMaxConnection = maxconnection;
Log.w(" Max Connection ", maxconnection + " " + " Adataarray :"
+ data.toString());
mState = IS_READY_TO_DRAW;
}
public void setState(int state) {
mState = state;
}
public int getColorValues(int index) {
if (mdataArray == null) {
return 0;
}
else if (index < 0)
return ((PieDetailsItem) mdataArray.get(0)).color;
else if (index > mdataArray.size())
return ((PieDetailsItem) mdataArray.get(mdataArray.size() - 1)).color;
else
return ((PieDetailsItem) mdataArray.get(mdataArray.size() - 1)).color;
}
main.xml
>
<LinearLayout android:id="#+id/pie_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
You're not going to use a TextView, you're just going to draw the text right on top of your pies.
refer to this:
Android Canvas.drawText
Post xml layouts for the views that you want.
Related
I need to tilt my SurfaceView by certain angle. SurfaceView renders a frame from WebRTC. But the render is always vertical. I need to rotate it by certain angle, say 30 degrees. I tried setting up setWillNotDraw(false); and adding this to my onDraw(Canvas canvas) method.
#Override
protected void onDraw(Canvas canvas) {
canvas.rotate(30, 220, 290);
super.onDraw(canvas);
}
This does not seem to work at all.
Here is my SurfaceView class:
public class SurfaceViewRenderer extends SurfaceView implements Callback, Callbacks {
private static final String TAG = "SurfaceViewRenderer";
private final String resourceName = this.getResourceName();
private final VideoLayoutMeasure videoLayoutMeasure = new VideoLayoutMeasure();
private final EglRenderer eglRenderer;
private RendererEvents rendererEvents;
private final Object layoutLock = new Object();
private boolean isFirstFrameRendered;
private int rotatedFrameWidth;
private int rotatedFrameHeight;
private int frameRotation;
private boolean enableFixedSize;
private int surfaceWidth;
private int surfaceHeight;
public SurfaceViewRenderer(Context context) {
super(context);
this.eglRenderer = new EglRenderer(this.resourceName);
this.getHolder().addCallback(this);
}
public SurfaceViewRenderer(Context context, AttributeSet attrs) {
super(context, attrs);
this.eglRenderer = new EglRenderer(this.resourceName);
this.getHolder().addCallback(this);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setWillNotDraw(false);
}
public void init(org.webrtc.EglBase.Context sharedContext, RendererEvents rendererEvents) {
this.init(sharedContext, rendererEvents, EglBase.CONFIG_PLAIN, new GlRectDrawer());
}
public void init(org.webrtc.EglBase.Context sharedContext, RendererEvents rendererEvents, int[] configAttributes, GlDrawer drawer) {
ThreadUtils.checkIsOnMainThread();
this.rendererEvents = rendererEvents;
Object var5 = this.layoutLock;
synchronized(this.layoutLock) {
this.rotatedFrameWidth = 0;
this.rotatedFrameHeight = 0;
this.frameRotation = 0;
}
this.eglRenderer.init(sharedContext, configAttributes, drawer);
}
public void release() {
this.eglRenderer.release();
}
public void addFrameListener(FrameListener listener, float scale, GlDrawer drawer) {
this.eglRenderer.addFrameListener(listener, scale, drawer);
}
public void addFrameListener(FrameListener listener, float scale) {
this.eglRenderer.addFrameListener(listener, scale);
}
public void removeFrameListener(FrameListener listener) {
this.eglRenderer.removeFrameListener(listener);
}
public void setEnableHardwareScaler(boolean enabled) {
ThreadUtils.checkIsOnMainThread();
this.enableFixedSize = enabled;
this.updateSurfaceSize();
}
public void setMirror(boolean mirror) {
this.eglRenderer.setMirror(mirror);
}
public void setScalingType(ScalingType scalingType) {
ThreadUtils.checkIsOnMainThread();
this.videoLayoutMeasure.setScalingType(scalingType);
}
public void setScalingType(ScalingType scalingTypeMatchOrientation, ScalingType scalingTypeMismatchOrientation) {
ThreadUtils.checkIsOnMainThread();
this.videoLayoutMeasure.setScalingType(scalingTypeMatchOrientation, scalingTypeMismatchOrientation);
}
public void setFpsReduction(float fps) {
this.eglRenderer.setFpsReduction(fps);
}
public void disableFpsReduction() {
this.eglRenderer.disableFpsReduction();
}
public void pauseVideo() {
this.eglRenderer.pauseVideo();
}
public void renderFrame(I420Frame frame) {
this.updateFrameDimensionsAndReportEvents(frame);
this.eglRenderer.renderFrame(frame);
}
protected void onMeasure(int widthSpec, int heightSpec) {
ThreadUtils.checkIsOnMainThread();
Object var4 = this.layoutLock;
Point size;
synchronized(this.layoutLock) {
size = this.videoLayoutMeasure.measure(widthSpec, heightSpec, this.rotatedFrameWidth, this.rotatedFrameHeight);
}
this.setMeasuredDimension(size.x, size.y);
this.logD("onMeasure(). New size: " + size.x + "x" + size.y);
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
ThreadUtils.checkIsOnMainThread();
this.eglRenderer.setLayoutAspectRatio((float)(right - left) / (float)(bottom - top));
this.updateSurfaceSize();
}
private void updateSurfaceSize() {
ThreadUtils.checkIsOnMainThread();
Object var1 = this.layoutLock;
synchronized(this.layoutLock) {
if(this.enableFixedSize && this.rotatedFrameWidth != 0 && this.rotatedFrameHeight != 0 && this.getWidth() != 0 && this.getHeight() != 0) {
float layoutAspectRatio = (float)this.getWidth() / (float)this.getHeight();
float frameAspectRatio = (float)this.rotatedFrameWidth / (float)this.rotatedFrameHeight;
int drawnFrameWidth;
int drawnFrameHeight;
if(frameAspectRatio > layoutAspectRatio) {
drawnFrameWidth = (int)((float)this.rotatedFrameHeight * layoutAspectRatio);
drawnFrameHeight = this.rotatedFrameHeight;
} else {
drawnFrameWidth = this.rotatedFrameWidth;
drawnFrameHeight = (int)((float)this.rotatedFrameWidth / layoutAspectRatio);
}
int width = Math.min(this.getWidth(), drawnFrameWidth);
int height = Math.min(this.getHeight(), drawnFrameHeight);
this.logD("updateSurfaceSize. Layout size: " + this.getWidth() + "x" + this.getHeight() + ", frame size: " + this.rotatedFrameWidth + "x" + this.rotatedFrameHeight + ", requested surface size: " + width + "x" + height + ", old surface size: " + this.surfaceWidth + "x" + this.surfaceHeight);
if(width != this.surfaceWidth || height != this.surfaceHeight) {
this.surfaceWidth = width;
this.surfaceHeight = height;
this.getHolder().setFixedSize(width, height);
}
} else {
this.surfaceWidth = this.surfaceHeight = 0;
this.getHolder().setSizeFromLayout();
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
ThreadUtils.checkIsOnMainThread();
this.eglRenderer.createEglSurface(holder.getSurface());
this.surfaceWidth = this.surfaceHeight = 0;
this.updateSurfaceSize();
}
public void surfaceDestroyed(SurfaceHolder holder) {
ThreadUtils.checkIsOnMainThread();
final CountDownLatch completionLatch = new CountDownLatch(1);
this.eglRenderer.releaseEglSurface(new Runnable() {
public void run() {
completionLatch.countDown();
}
});
ThreadUtils.awaitUninterruptibly(completionLatch);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
ThreadUtils.checkIsOnMainThread();
this.logD("surfaceChanged: format: " + format + " size: " + width + "x" + height);
}
private String getResourceName() {
try {
return this.getResources().getResourceEntryName(this.getId()) + ": ";
} catch (NotFoundException var2) {
return "";
}
}
private void updateFrameDimensionsAndReportEvents(I420Frame frame) {
Object var2 = this.layoutLock;
synchronized(this.layoutLock) {
if(!this.isFirstFrameRendered) {
this.isFirstFrameRendered = true;
this.logD("Reporting first rendered frame.");
if(this.rendererEvents != null) {
this.rendererEvents.onFirstFrameRendered();
}
}
if(this.rotatedFrameWidth != frame.rotatedWidth() || this.rotatedFrameHeight != frame.rotatedHeight() || this.frameRotation != frame.rotationDegree) {
this.logD("Reporting frame resolution changed to " + frame.width + "x" + frame.height + " with rotation " + frame.rotationDegree);
if(this.rendererEvents != null) {
this.rendererEvents.onFrameResolutionChanged(frame.width, frame.height, frame.rotationDegree);
}
this.rotatedFrameWidth = frame.rotatedWidth();
this.rotatedFrameHeight = frame.rotatedHeight();
this.frameRotation = frame.rotationDegree;
this.post(new Runnable() {
public void run() {
SurfaceViewRenderer.this.updateSurfaceSize();
SurfaceViewRenderer.this.requestLayout();
}
});
}
}
}
#Override
protected void onDraw(Canvas canvas) {
canvas.rotate(180, 220, 290);
super.onDraw(canvas);
}
private void logD(String string) {
Logging.d("SurfaceViewRenderer", this.resourceName + string);
}
}
You could use TextureView instead.
From the documentation:
Unlike SurfaceView, TextureView does not create a separate window but behaves as a regular View. This key difference allows a TextureView to be moved, transformed, animated, etc.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have an app in which I have to make an animation similar to that of a radar signal. But I am not quite sure of how to accomplish this. Any suggestions in this regard will be appreciated
Example of image like animation
The answer is already given here at this so post see here given by Ajay Pandya
You can use some below libraries
https://github.com/jfabrix101/RadarCustomVIew
https://github.com/gpfduoduo/RadarScanView
i.e
Radar.java
public class RadarView extends View {
private final String LOG = "RadarView";
private final int POINT_ARRAY_SIZE = 25;
private int fps = 100;
private boolean showCircles = true;
float alpha = 0;
Point latestPoint[] = new Point[POINT_ARRAY_SIZE];
Paint latestPaint[] = new Paint[POINT_ARRAY_SIZE];
public RadarView(Context context) {
this(context, null);
}
public RadarView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RadarView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Paint localPaint = new Paint();
localPaint.setColor(Color.GREEN);
localPaint.setAntiAlias(true);
localPaint.setStyle(Paint.Style.STROKE);
localPaint.setStrokeWidth(1.0F);
localPaint.setAlpha(0);
int alpha_step = 255 / POINT_ARRAY_SIZE;
for (int i=0; i < latestPaint.length; i++) {
latestPaint[i] = new Paint(localPaint);
latestPaint[i].setAlpha(255 - (i* alpha_step));
}
}
android.os.Handler mHandler = new android.os.Handler();
Runnable mTick = new Runnable() {
#Override
public void run() {
invalidate();
mHandler.postDelayed(this, 1000 / fps);
}
};
public void startAnimation() {
mHandler.removeCallbacks(mTick);
mHandler.post(mTick);
}
public void stopAnimation() {
mHandler.removeCallbacks(mTick);
}
public void setFrameRate(int fps) { this.fps = fps; }
public int getFrameRate() { return this.fps; };
public void setShowCircles(boolean showCircles) { this.showCircles = showCircles; }
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
int r = Math.min(width, height);
//canvas.drawRect(0, 0, getWidth(), getHeight(), localPaint);
int i = r / 2;
int j = i - 1;
Paint localPaint = latestPaint[0]; // GREEN
if (showCircles) {
canvas.drawCircle(i, i, j, localPaint);
canvas.drawCircle(i, i, j, localPaint);
canvas.drawCircle(i, i, j * 3 / 4, localPaint);
canvas.drawCircle(i, i, j >> 1, localPaint);
canvas.drawCircle(i, i, j >> 2, localPaint);
}
alpha -= 0.5;
if (alpha < -360) alpha = 0;
double angle = Math.toRadians(alpha);
int offsetX = (int) (i + (float)(i * Math.cos(angle)));
int offsetY = (int) (i - (float)(i * Math.sin(angle)));
latestPoint[0]= new Point(offsetX, offsetY);
for (int x=POINT_ARRAY_SIZE-1; x > 0; x--) {
latestPoint[x] = latestPoint[x-1];
}
int lines = 0;
for (int x = 0; x < POINT_ARRAY_SIZE; x++) {
Point point = latestPoint[x];
if (point != null) {
canvas.drawLine(i, i, point.x, point.y, latestPaint[x]);
}
}
lines = 0;
for (Point p : latestPoint) if (p != null) lines++;
boolean debug = false;
if (debug) {
StringBuilder sb = new StringBuilder(" >> ");
for (Point p : latestPoint) {
if (p != null) sb.append(" (" + p.x + "x" + p.y + ")");
}
Log.d(LOG, sb.toString());
// " - R:" + r + ", i=" + i +
// " - Size: " + width + "x" + height +
// " - Angle: " + angle +
// " - Offset: " + offsetX + "," + offsetY);
}
}
}
in your activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#android:color/black">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start"
android:onClick="startAniamtion"/>
<frusso.radartest.RadarView
android:id="#+id/radarView"
android:layout_width="240dp"
android:layout_height="240dp"
android:layout_gravity="center_horizontal"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stop"
android:onClick="stopAnimation"/>
Activity.java
public class MainActivity extends Activity {
RadarView mRadarView = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRadarView = (RadarView) findViewById(R.id.radarView);
mRadarView.setShowCircles(true);
}
public void stopAnimation(View view) {
if (mRadarView != null) mRadarView.stopAnimation();
}
public void startAnimation(View view) {
if (mRadarView != null) mRadarView.startAnimation();
}
}
Hi i have created custom view "Number Bar" which is working fine. I just want to add labels on each indicator. I tried that but when i draw text it is not visible because view is not getting height for that. Please check image below thanks.
View onDraw Source Code
protected void onDraw(Canvas canvas) {
int indicatorWidthHeight = Utils.dpToPx(getContext(), indicatorSize);
indicatorRadius = indicatorWidthHeight / 2;
int cx = indicatorWidthHeight / 2;
int cy = indicatorWidthHeight / 2;
int totalIndicators = 5;
int totalLines = totalIndicators - 1;
int lineWidth = (getMeasuredWidth() - (indicatorWidthHeight * totalIndicators)) / totalLines;
linePaint.setStrokeWidth(Utils.dpToPx(getContext(), lineHeight));
for (int i = 0; i < circles.length; i++) {
if (selected >= i) {
indicatorPaint.setColor(selectedBackgroundColor);
textPaint.setColor(selectedTextColor);
} else {
indicatorPaint.setColor(backgroundColor);
textPaint.setColor(textColor);
}
if (selected >= i + 1) {
linePaint.setColor(selectedBackgroundColor);
} else {
linePaint.setColor(backgroundColor);
}
int nCx = cx + (lineWidth + indicatorRadius * 2) * i;
circles[i].setRadius(indicatorRadius);
circles[i].setX(nCx);
circles[i].setY(cy);
canvas.drawCircle(nCx, cy, indicatorRadius, indicatorPaint);
String text = "" + (i+1);
textPaint.getTextBounds(text, 0, text.length(), rect);
canvas.drawText(text, nCx, cy+rect.height()/2, textPaint);
// Draw lines one less than circles
if (i != circles.length - 1) {
int startX = nCx + indicatorRadius;
int stopX = nCx + indicatorRadius + lineWidth;
lines[i].setStartX(startX);
lines[i].setStartY(cy);
lines[i].setStopX(stopX);
lines[i].setStopY(cy);
canvas.drawLine(startX, cy, stopX, cy, linePaint);
}
}
}
View Full Source Code
public class NumberBar extends View {
public static final int DEFAULT_TEXT_SIZE = 16;
public static final int DEF_INDICATOR_SIZE = 20;
Rect rect = new Rect();
Circle[] circles = new Circle[5];
Line[] lines = new Line[4];
private int backgroundColor, textColor, selectedBackgroundColor, selectedTextColor, indicatorSize, lineHeight, selected;
private Paint indicatorPaint;
private Paint textPaint;
private Paint linePaint;
private int indicatorRadius;
private boolean enabled = true;
public NumberBar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NumberBar, 0, 0);
try {
backgroundColor = typedArray.getInteger(R.styleable.NumberBar_backgroundColor, Color.parseColor("#eeeeee"));
selectedBackgroundColor = typedArray.getInteger(R.styleable.NumberBar_selectedBackgroundColor, Color.parseColor("#0171fe"));
textColor = typedArray.getInteger(R.styleable.NumberBar_textColor, Color.parseColor("#c8c8c8"));
selectedTextColor = typedArray.getInteger(R.styleable.NumberBar_selectedTextColor, Color.parseColor("#ffffff"));
indicatorSize = typedArray.getInteger(R.styleable.NumberBar_indicatorSize, DEF_INDICATOR_SIZE);
lineHeight = typedArray.getInteger(R.styleable.NumberBar_lineHeight, 3);
selected = typedArray.getInteger(R.styleable.NumberBar_selected, 0);
enabled = typedArray.getBoolean(R.styleable.NumberBar_enabled, true);
} finally {
typedArray.recycle();
}
for (int i = 0; i < circles.length; i++) {
circles[i] = new Circle();
}
for (int i = 0; i < lines.length; i++) {
lines[i] = new Line();
}
indicatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
indicatorPaint.setStyle(Paint.Style.FILL);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setTextSize(Utils.spToPx(getContext(), DEFAULT_TEXT_SIZE));
linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
linePaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
#Override
protected void onDraw(Canvas canvas) {
int indicatorWidthHeight = Utils.dpToPx(getContext(), indicatorSize);
indicatorRadius = indicatorWidthHeight / 2;
int cx = indicatorWidthHeight / 2;
int cy = indicatorWidthHeight / 2;
int totalIndicators = 5;
int totalLines = totalIndicators - 1;
int lineWidth = (getMeasuredWidth() - (indicatorWidthHeight * totalIndicators)) / totalLines;
linePaint.setStrokeWidth(Utils.dpToPx(getContext(), lineHeight));
for (int i = 0; i < circles.length; i++) {
if (selected >= i) {
indicatorPaint.setColor(selectedBackgroundColor);
textPaint.setColor(selectedTextColor);
} else {
indicatorPaint.setColor(backgroundColor);
textPaint.setColor(textColor);
}
if (selected >= i + 1) {
linePaint.setColor(selectedBackgroundColor);
} else {
linePaint.setColor(backgroundColor);
}
int nCx = cx + (lineWidth + indicatorRadius * 2) * i;
circles[i].setRadius(indicatorRadius);
circles[i].setX(nCx);
circles[i].setY(cy);
canvas.drawCircle(nCx, cy, indicatorRadius, indicatorPaint);
String text = "" + (i+1);
textPaint.getTextBounds(text, 0, text.length(), rect);
canvas.drawText(text, nCx, cy+rect.height()/2, textPaint);
// Draw lines one less than circles
if (i != circles.length - 1) {
int startX = nCx + indicatorRadius;
int stopX = nCx + indicatorRadius + lineWidth;
lines[i].setStartX(startX);
lines[i].setStartY(cy);
lines[i].setStopX(stopX);
lines[i].setStopY(cy);
canvas.drawLine(startX, cy, stopX, cy, linePaint);
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!enabled) {
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
handleDownTouch(event.getX(), event.getY());
break;
}
return true;
}
private void handleDownTouch(float eventX, float eventY) {
for (int i = 0; i < circles.length; i++) {
if (isCircleClicked(eventX, eventY, circles[i])) { // Toast.makeText(NumberBar.this.getContext(), "Circle Clicked: " + i, Toast.LENGTH_SHORT).show();
this.selected = i;
invalidate();
return;
}
}
for (int i = 0; i < lines.length; i++) {
if (inLine(lines[i].getStartPoint(), lines[i].getStopPoint(), new Point((int)eventX, (int)eventY))) {
this.selected = i+1;
invalidate();
return; // Toast.makeText(NumberBar.this.getContext(), "Line: " + i, Toast.LENGTH_SHORT).show();
}
}
}
// is BC inline with AC or visa-versa
public boolean inLine(Point A, Point B, Point C) {
int offset = 5;
return C.x >= A.x && C.x <= B.x && (C.y <= (B.y-lineHeight+ offset) || C.y <= (B.y-lineHeight- offset));
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Don't measure width its most or which user will give
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int height;
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(indicatorSize, heightSize);
} else {
//Be whatever you want
height = indicatorSize;
}
//MUST CALL THIS
setMeasuredDimension(widthSize, height);
setMeasuredDimension(getMeasuredWidth(), Utils.dpToPx(getContext(), indicatorSize));
}
private boolean isCircleClicked(float ex, float ey, Circle circle) {
return Math.sqrt((circle.getX() - ex) * (circle.getX() - ex) + (circle.getY() - ey) * (circle.getY() - ey)) < circle.getRadius()+4;
}
public int getBackgroundColor() {
return backgroundColor;
}
#Override
public void setBackgroundColor(int backgroundColor) {
this.backgroundColor = backgroundColor;
invalidate();
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
invalidate();
}
public int getSelectedBackgroundColor() {
return selectedBackgroundColor;
}
public void setSelectedBackgroundColor(int selectedBackgroundColor) {
this.selectedBackgroundColor = selectedBackgroundColor;
invalidate();
}
public int getSelectedTextColor() {
return selectedTextColor;
}
public void setSelectedTextColor(int selectedTextColor) {
this.selectedTextColor = selectedTextColor;
invalidate();
}
public int getIndicatorSize() {
return indicatorSize;
}
public void setIndicatorSize(int indicatorSize) {
this.indicatorSize = indicatorSize;
invalidate();
requestLayout();
}
public int getLineHeight() {
return lineHeight;
}
public void setLineHeight(int lineHeight) {
this.lineHeight = lineHeight;
invalidate();
requestLayout();
}
public int getSelected() {
return selected;
}
public void setSelected(int selected) {
this.selected = selected;
invalidate();
}
private class Circle {
int x, y;
int radius;
public Circle() {
}
public Circle(int x, int y, int radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
}
class Line {
Point startPoint = new Point();
Point stopPoint = new Point();
public int getStartX() {
return startPoint.x;
}
public void setStartX(int startX) {
this.startPoint.x = startX;
}
public int getStartY() {
return startPoint.y;
}
public void setStartY(int startY) {
this.startPoint.y = startY;
}
public int getStopX() {
return stopPoint.x;
}
public void setStopX(int stopX) {
this.stopPoint.x = stopX;
}
public int getStopY() {
return stopPoint.y;
}
public void setStopY(int stopY) {
this.stopPoint.y = stopY;
}
public Point getStartPoint() {
return startPoint;
}
public Point getStopPoint() {
return stopPoint;
}
}
#Override
public boolean isEnabled() {
return enabled;
}
#Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
} }
I am having a WaveFormView on which I want to change the color of it while playing Audio file and as the Audio is paused it should be stopped coloring at that certain point and when resumed it should continue forward with coloring. I am not getting how to do it in my code..
This is the screen shot of my generated waveform. Now when I will click on Play button it should change the color of waveform gradually with red color (from start to end slowly).
Here is my code to draw waveform view.
WaveFormView.class
public class WaveformView extends View {
public interface WaveformListener {
public void waveformFling(float x);
public void waveformDraw();
}
;
// Colors
private Paint mGridPaint;
private Paint mSelectedLinePaint;
private Paint mUnselectedLinePaint;
private Paint mUnselectedBkgndLinePaint;
private Paint mBorderLinePaint;
private Paint mPlaybackLinePaint;
private Paint mTimecodePaint;
private SoundFile mSoundFile;
private int[] mLenByZoomLevel;
private double[][] mValuesByZoomLevel;
private double[] mZoomFactorByZoomLevel;
private int[] mHeightsAtThisZoomLevel;
private int mZoomLevel;
private int mNumZoomLevels;
private int mSampleRate;
private int mSamplesPerFrame;
private int mOffset;
private int mSelectionStart;
private int mSelectionEnd;
private int mPlaybackPos;
private float mDensity;
private float mInitialScaleSpan;
private WaveformListener mListener;
private GestureDetector mGestureDetector;
private ScaleGestureDetector mScaleGestureDetector;
private boolean mInitialized;
Color color;
public WaveformView(Context context, AttributeSet attrs) {
super(context, attrs);
// We don't want keys, the markers get these
setFocusable(false);
mGridPaint = new Paint();
mGridPaint.setAntiAlias(false);
mGridPaint.setColor(
getResources().getColor(R.color.grid_line));
mSelectedLinePaint = new Paint();
mSelectedLinePaint.setAntiAlias(false);
mSelectedLinePaint.setColor(
getResources().getColor(R.color.waveform_selected));
mUnselectedLinePaint = new Paint();
mUnselectedLinePaint.setAntiAlias(false);
mUnselectedLinePaint.setColor(
getResources().getColor(R.color.waveform_unselected));
mUnselectedBkgndLinePaint = new Paint();
mUnselectedBkgndLinePaint.setAntiAlias(false);
mUnselectedBkgndLinePaint.setColor(
getResources().getColor(
R.color.selection_border));
mBorderLinePaint = new Paint();
mBorderLinePaint.setAntiAlias(true);
mBorderLinePaint.setStrokeWidth(1.5f);
mBorderLinePaint.setPathEffect(
new DashPathEffect(new float[]{3.0f, 2.0f}, 0.0f));
mBorderLinePaint.setColor(
getResources().getColor(R.color.selection_border));
mPlaybackLinePaint = new Paint();
mPlaybackLinePaint.setAntiAlias(false);
mPlaybackLinePaint.setColor(
getResources().getColor(R.color.playback_indicator));
mTimecodePaint = new Paint();
mTimecodePaint.setTextSize(12);
mTimecodePaint.setAntiAlias(true);
mTimecodePaint.setColor(
getResources().getColor(R.color.timecode));
mTimecodePaint.setShadowLayer(
2, 1, 1,
getResources().getColor(R.color.timecode_shadow));
mGestureDetector = new GestureDetector(
context,
new GestureDetector.SimpleOnGestureListener() {
public boolean onFling(
MotionEvent e1, MotionEvent e2, float vx, float vy) {
mListener.waveformFling(vx);
return true;
}
});
mSoundFile = null;
mLenByZoomLevel = null;
mValuesByZoomLevel = null;
mHeightsAtThisZoomLevel = null;
mOffset = 0;
mPlaybackPos = -1;
mSelectionStart = 0;
mSelectionEnd = 0;
mDensity = 1.0f;
mInitialized = false;
}
public boolean hasSoundFile() {
return mSoundFile != null;
}
public void setSoundFile(SoundFile soundFile) {
mSoundFile = soundFile;
mSampleRate = mSoundFile.getSampleRate();
mSamplesPerFrame = mSoundFile.getSamplesPerFrame();
computeDoublesForAllZoomLevels();
mHeightsAtThisZoomLevel = null;
}
/**
* Called once when a new sound file is added
*/
private void computeDoublesForAllZoomLevels() {
int numFrames = mSoundFile.getNumFrames();
int[] frameGains = mSoundFile.getFrameGains();
double[] smoothedGains = new double[numFrames];
if (numFrames == 1) {
smoothedGains[0] = frameGains[0];
} else if (numFrames == 2) {
smoothedGains[0] = frameGains[0];
smoothedGains[1] = frameGains[1];
} else if (numFrames > 2) {
smoothedGains[0] = (double)(
(frameGains[0] / 2.0) +
(frameGains[1] / 2.0));
for (int i = 1; i < numFrames - 1; i++) {
smoothedGains[i] = (double)(
(frameGains[i - 1] / 3.0) +
(frameGains[i ] / 3.0) +
(frameGains[i + 1] / 3.0));
}
smoothedGains[numFrames - 1] = (double)(
(frameGains[numFrames - 2] / 2.0) +
(frameGains[numFrames - 1] / 2.0));
}
// Make sure the range is no more than 0 - 255
double maxGain = 1.0;
for (int i = 0; i < numFrames; i++) {
if (smoothedGains[i] > maxGain) {
maxGain = smoothedGains[i];
}
}
double scaleFactor = 1.0;
if (maxGain > 255.0) {
scaleFactor = 255 / maxGain;
}
// Build histogram of 256 bins and figure out the new scaled max
maxGain = 0;
int gainHist[] = new int[256];
for (int i = 0; i < numFrames; i++) {
int smoothedGain = (int)(smoothedGains[i] * scaleFactor);
if (smoothedGain < 0)
smoothedGain = 0;
if (smoothedGain > 255)
smoothedGain = 255;
if (smoothedGain > maxGain)
maxGain = smoothedGain;
gainHist[smoothedGain]++;
}
// Re-calibrate the min to be 5%
double minGain = 0;
int sum = 0;
while (minGain < 255 && sum < numFrames / 20) {
sum += gainHist[(int)minGain];
minGain++;
}
// Re-calibrate the max to be 99%
sum = 0;
while (maxGain > 2 && sum < numFrames / 100) {
sum += gainHist[(int)maxGain];
maxGain--;
}
// Compute the heights
double[] heights = new double[numFrames];
double range = maxGain - minGain;
for (int i = 0; i < numFrames; i++) {
double value = (smoothedGains[i] * scaleFactor - minGain) / range;
if (value < 0.0)
value = 0.0;
if (value > 1.0)
value = 1.0;
heights[i] = value * value;
}
mNumZoomLevels = 5;
mLenByZoomLevel = new int[5];
mZoomFactorByZoomLevel = new double[5];
mValuesByZoomLevel = new double[5][];
// Level 0 is doubled, with interpolated values
mLenByZoomLevel[0] = numFrames * 2;
mZoomFactorByZoomLevel[0] = 2.0;
mValuesByZoomLevel[0] = new double[mLenByZoomLevel[0]];
if (numFrames > 0) {
mValuesByZoomLevel[0][0] = 0.5 * heights[0];
mValuesByZoomLevel[0][1] = heights[0];
}
for (int i = 1; i < numFrames; i++) {
mValuesByZoomLevel[0][2 * i] = 0.5 * (heights[i - 1] + heights[i]);
mValuesByZoomLevel[0][2 * i + 1] = heights[i];
}
// Level 1 is normal
mLenByZoomLevel[1] = numFrames;
mValuesByZoomLevel[1] = new double[mLenByZoomLevel[1]];
mZoomFactorByZoomLevel[1] = 1.0;
for (int i = 0; i < mLenByZoomLevel[1]; i++) {
mValuesByZoomLevel[1][i] = heights[i];
}
// 3 more levels are each halved
for (int j = 2; j < 5; j++) {
mLenByZoomLevel[j] = mLenByZoomLevel[j - 1] / 2;
mValuesByZoomLevel[j] = new double[mLenByZoomLevel[j]];
mZoomFactorByZoomLevel[j] = mZoomFactorByZoomLevel[j - 1] / 2.0;
for (int i = 0; i < mLenByZoomLevel[j]; i++) {
mValuesByZoomLevel[j][i] =
0.5 * (mValuesByZoomLevel[j - 1][2 * i] +
mValuesByZoomLevel[j - 1][2 * i + 1]);
}
}
if (numFrames > 5000) {
mZoomLevel = 3;
} else if (numFrames > 1000) {
mZoomLevel = 2;
} else if (numFrames > 300) {
mZoomLevel = 1;
} else {
mZoomLevel = 0;
}
mInitialized = true;
}
public boolean canZoomIn() {
return (mZoomLevel > 0);
}
public void zoomIn() {
if (canZoomIn()) {
mZoomLevel--;
mSelectionStart *= 2;
mSelectionEnd *= 2;
mHeightsAtThisZoomLevel = null;
int offsetCenter = mOffset + getMeasuredWidth() / 2;
offsetCenter *= 2;
mOffset = offsetCenter - getMeasuredWidth() / 2;
if (mOffset < 0)
mOffset = 0;
invalidate();
}
}
public boolean canZoomOut() {
return (mZoomLevel < mNumZoomLevels - 1);
}
public void zoomOut() {
if (canZoomOut()) {
mZoomLevel++;
mSelectionStart /= 2;
mSelectionEnd /= 2;
int offsetCenter = mOffset + getMeasuredWidth() / 2;
offsetCenter /= 2;
mOffset = offsetCenter - getMeasuredWidth() / 2;
if (mOffset < 0)
mOffset = 0;
mHeightsAtThisZoomLevel = null;
invalidate();
}
}
public double pixelsToSeconds(int pixels) {
double z = mZoomFactorByZoomLevel[mZoomLevel];
return (pixels * (double)mSamplesPerFrame / (mSampleRate * z));
}
public void setListener(WaveformListener listener) {
mListener = listener;
}
public void recomputeHeights(float density) {
mHeightsAtThisZoomLevel = null;
mDensity = density;
mTimecodePaint.setTextSize((int)(12 * density));
invalidate();
}
protected void drawWaveformLine(Canvas canvas,
int x, int y0, int y1,
Paint paint) {
canvas.drawLine(x, y0, x, y1, paint);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mSoundFile == null)
return;
if (mHeightsAtThisZoomLevel == null)
computeIntsForThisZoomLevel();
DisplayMetrics displaymetrics = getContext().getResources().getDisplayMetrics();
int height = displaymetrics.heightPixels;
int widths = displaymetrics.widthPixels;
// Draw waveform
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
int start = mOffset;
int width = mHeightsAtThisZoomLevel.length - start;
int ctr = measuredHeight / 2;
Log.e("wid",String.valueOf(width));
Log.e("widCal",String.valueOf(mHeightsAtThisZoomLevel.length));
Log.e("widstart",String.valueOf(start));
if (width > measuredWidth)
width = measuredWidth;
Log.e("measured",String.valueOf(measuredWidth));
// Draw grid
double onePixelInSecs = pixelsToSeconds(1);
boolean onlyEveryFiveSecs = (onePixelInSecs > 1.0 / 50.0);
double fractionalSecs = mOffset * onePixelInSecs;
int integerSecs = (int) fractionalSecs;
int i = 0;
while (i < width) {
i++;
fractionalSecs += onePixelInSecs;
int integerSecsNew = (int) fractionalSecs;
if (integerSecsNew != integerSecs) {
integerSecs = integerSecsNew;
if (!onlyEveryFiveSecs || 0 == (integerSecs % 5)) {
canvas.drawLine(i, 0, i, measuredHeight, mGridPaint);
}
}
}
// Draw waveform
for ( i = 0; i < width; i++) {
Paint paint;
if (i + start >= mSelectionStart &&
i + start < mSelectionEnd) {
paint = mSelectedLinePaint;
// paint.setColor(color);
} else {
drawWaveformLine(canvas, ((widths/width)*i), 0, measuredHeight,
mUnselectedBkgndLinePaint);
paint = mUnselectedLinePaint;
}
drawWaveformLine(
canvas, ((widths/width)*i),
ctr - mHeightsAtThisZoomLevel[start + i],
ctr + 1 + mHeightsAtThisZoomLevel[start + i],
paint);
if (i + start == mPlaybackPos) {
canvas.drawLine(i, 0, i, measuredHeight, mPlaybackLinePaint);
}
}
if (mListener != null) {
mListener.waveformDraw();
}
}
private void computeIntsForThisZoomLevel() {
int halfHeight = (getMeasuredHeight() / 2) - 1;
mHeightsAtThisZoomLevel = new int[mLenByZoomLevel[mZoomLevel]];
for (int i = 0; i < mLenByZoomLevel[mZoomLevel]; i++) {
mHeightsAtThisZoomLevel[i] =
(int)(mValuesByZoomLevel[mZoomLevel][i] * halfHeight);
}
}
}
MainActivity.class
public class MainActivity extends AppCompatActivity implements WaveformView.WaveformListener {
WaveformView mWaveformView;
SoundFile mSoundFile;
private float mDensity;
private File mFile;
private String mFilename;
private long mLoadingLastUpdateTime;
boolean mLoadingKeepGoing;
boolean mFinishActivity;
private ProgressDialog mProgressDialog;
String mTitle,mArtist;
private Thread mLoadSoundFileThread;
private Thread mRecordAudioThread;
private Thread mSaveSoundFileThread;
private boolean mIsPlaying;
private SamplePlayer mPlayer;
private String mInfoContent;
private int mWidth;
private int mMaxPos;
private int mStartPos;
private int mEndPos;
private boolean mStartVisible;
private boolean mEndVisible;
private int mLastDisplayedStartPos;
private int mLastDisplayedEndPos;
private int mOffset;
private int mOffsetGoal;
private int mFlingVelocity;
private int mPlayStartMsec;
private int mPlayEndMsec;
private Handler mHandler;
Button pla;
MediaPlayer mediaPlayer;
boolean ismIsPlaying;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pla = (Button)findViewById(R.id.play);
mWaveformView = (WaveformView)findViewById(R.id.waveform);
mWaveformView.setListener(this);
mHandler = new Handler();
Uri uri = Uri.parse("/sdcard/audio_file.mp3");
mediaPlayer = new MediaPlayer();
mediaPlayer = MediaPlayer.create(getApplicationContext(),uri);
loadGui();
loadFromFile();
}
/**
* Called from both onCreate and onConfigurationChanged
* (if the user switched layouts)
*/
private void loadGui() {
// Inflate our UI from its XML layout description.
setContentView(R.layout.activity_main);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mDensity = metrics.density;
mWaveformView = (WaveformView)findViewById(R.id.waveform);
mWaveformView.setListener(this);
if (mSoundFile != null && !mWaveformView.hasSoundFile()) {
mWaveformView.setSoundFile(mSoundFile);
mWaveformView.recomputeHeights(mDensity);
}
}
private void loadFromFile() {
mFilename = "/sdcard/audio_file.mp3";
mFile = new File(mFilename);
SongMetadataReader metadataReader = new SongMetadataReader(
this, mFilename);
mTitle = metadataReader.mTitle;
mArtist = metadataReader.mArtist;
String titleLabel = mTitle;
if (mArtist != null && mArtist.length() > 0) {
titleLabel += " - " + mArtist;
}
setTitle(titleLabel);
mLoadingLastUpdateTime = getCurrentTime();
mLoadingKeepGoing = true;
mFinishActivity = false;
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setTitle("Loading...");
mProgressDialog.setCancelable(true);
mProgressDialog.setOnCancelListener(
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
mLoadingKeepGoing = false;
mFinishActivity = true;
}
});
mProgressDialog.show();
final SoundFile.ProgressListener listener =
new SoundFile.ProgressListener() {
public boolean reportProgress(double fractionComplete) {
long now = getCurrentTime();
if (now - mLoadingLastUpdateTime > 100) {
mProgressDialog.setProgress(
(int) (mProgressDialog.getMax() * fractionComplete));
mLoadingLastUpdateTime = now;
}
return mLoadingKeepGoing;
}
};
// Load the sound file in a background thread
mLoadSoundFileThread = new Thread() {
public void run() {
try {
mSoundFile = SoundFile.create(mFile.getAbsolutePath(), listener);
if (mSoundFile == null) {
mProgressDialog.dismiss();
String name = mFile.getName().toLowerCase();
String[] components = name.split("\\.");
String err;
if (components.length < 2) {
err = getResources().getString(
R.string.no_extension_error);
} else {
err = getResources().getString(
R.string.bad_extension_error) + " " +
components[components.length - 1];
}
final String finalErr = err;
Runnable runnable = new Runnable() {
public void run() {
showFinalAlert(new Exception(), finalErr);
}
};
mHandler.post(runnable);
return;
}
mPlayer = new SamplePlayer(mSoundFile);
} catch (final Exception e) {
mProgressDialog.dismiss();
e.printStackTrace();
mInfoContent = e.toString();
runOnUiThread(new Runnable() {
public void run() {
}
});
Runnable runnable = new Runnable() {
public void run() {
showFinalAlert(e, getResources().getText(R.string.read_error));
}
};
mHandler.post(runnable);
return;
}
mProgressDialog.dismiss();
if (mLoadingKeepGoing) {
Runnable runnable = new Runnable() {
public void run() {
finishOpeningSoundFile();
}
};
mHandler.post(runnable);
} else if (mFinishActivity){
MainActivity.this.finish();
}
}
};
mLoadSoundFileThread.start();
}
private void finishOpeningSoundFile() {
mWaveformView.setSoundFile(mSoundFile);
mWaveformView.recomputeHeights(mDensity);
Log.e("sound file",mFilename);
Log.e("sound", String.valueOf(mSoundFile));
}
/**
* Show a "final" alert dialog that will exit the activity
* after the user clicks on the OK button. If an exception
* is passed, it's assumed to be an error condition, and the
* dialog is presented as an error, and the stack trace is
* logged. If there's no exception, it's a success message.
*/
private void showFinalAlert(Exception e, CharSequence message) {
CharSequence title;
if (e != null) {
Log.e("Ringdroid", "Error: " + message);
Log.e("Ringdroid", getStackTrace(e));
title = getResources().getText(R.string.alert_title_failure);
setResult(RESULT_CANCELED, new Intent());
} else {
Log.v("Ringdroid", "Success: " + message);
title = getResources().getText(R.string.alert_title_success);
}
new AlertDialog.Builder(MainActivity.this)
.setTitle(title)
.setMessage(message)
.setPositiveButton(
R.string.alert_ok_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
finish();
}
})
.setCancelable(false)
.show();
}
private void showFinalAlert(Exception e, int messageResourceId) {
showFinalAlert(e, getResources().getText(messageResourceId));
}
#Override
public void waveformTouchStart(float x) {
}
#Override
public void waveformTouchMove(float x) {
}
#Override
public void waveformTouchEnd() {
}
#Override
public void waveformFling(float x) {
}
#Override
public void waveformDraw() {
mWidth = mWaveformView.getMeasuredWidth();
if (mOffsetGoal != mOffset) {
// updateDisplay();
}
else if (mIsPlaying) {
// updateDisplay();
} else if (mFlingVelocity != 0) {
// updateDisplay();
}
}
private long getCurrentTime() {
return System.nanoTime() / 1000000;
}
private String getStackTrace(Exception e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
return writer.toString();
}
public void buttonClick(View view) {
Toast.makeText(MainActivity.this, "test", Toast.LENGTH_SHORT).show();
mediaPlayer.start();
ismIsPlaying = true;
}
}
In your onDraw(Canvas canvas) add the following lines
if (i + start <= mPlaybackPos) {
Paint mPaint = new Paint(paint);
mPaint.setColor(Color.RED);
drawWaveformLine(
canvas, ((widths/width)*i),
ctr - mHeightsAtThisZoomLevel[start + i],
ctr + 1 + mHeightsAtThisZoomLevel[start + i],
mPaint);
}
add them above the line:
if (i + start == mPlaybackPos) {
And if this works, consider to allocate the Paint-object outside the onDraw() method.
So here is the thing. I am monitoring certain distances, and i would like to display them in a radar animation. The base radar image would be something like this (not exactly)
where every circle means a distance range. The idea is that the dot moves towards the circles as the distance changes. My initial approach was to make different images of the same radar with the dot on each circle and simply switch them according the distance. But then i wonder if there any chance(performant, and that works fine on different resolutions) to have one base image of the radar and simply move the dot. I hope I am being clear and if anyone has an idea i would be very thankful
I am not posting any code, cause i need the idea, then ill struggle with the implementation
Have you tried these examples?
https://github.com/jfabrix101/RadarCustomVIew
https://github.com/gpfduoduo/RadarScanView
i.e
Radar.java
public class RadarView extends View {
private final String LOG = "RadarView";
private final int POINT_ARRAY_SIZE = 25;
private int fps = 100;
private boolean showCircles = true;
float alpha = 0;
Point latestPoint[] = new Point[POINT_ARRAY_SIZE];
Paint latestPaint[] = new Paint[POINT_ARRAY_SIZE];
public RadarView(Context context) {
this(context, null);
}
public RadarView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RadarView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Paint localPaint = new Paint();
localPaint.setColor(Color.GREEN);
localPaint.setAntiAlias(true);
localPaint.setStyle(Paint.Style.STROKE);
localPaint.setStrokeWidth(1.0F);
localPaint.setAlpha(0);
int alpha_step = 255 / POINT_ARRAY_SIZE;
for (int i=0; i < latestPaint.length; i++) {
latestPaint[i] = new Paint(localPaint);
latestPaint[i].setAlpha(255 - (i* alpha_step));
}
}
android.os.Handler mHandler = new android.os.Handler();
Runnable mTick = new Runnable() {
#Override
public void run() {
invalidate();
mHandler.postDelayed(this, 1000 / fps);
}
};
public void startAnimation() {
mHandler.removeCallbacks(mTick);
mHandler.post(mTick);
}
public void stopAnimation() {
mHandler.removeCallbacks(mTick);
}
public void setFrameRate(int fps) { this.fps = fps; }
public int getFrameRate() { return this.fps; };
public void setShowCircles(boolean showCircles) { this.showCircles = showCircles; }
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
int r = Math.min(width, height);
//canvas.drawRect(0, 0, getWidth(), getHeight(), localPaint);
int i = r / 2;
int j = i - 1;
Paint localPaint = latestPaint[0]; // GREEN
if (showCircles) {
canvas.drawCircle(i, i, j, localPaint);
canvas.drawCircle(i, i, j, localPaint);
canvas.drawCircle(i, i, j * 3 / 4, localPaint);
canvas.drawCircle(i, i, j >> 1, localPaint);
canvas.drawCircle(i, i, j >> 2, localPaint);
}
alpha -= 0.5;
if (alpha < -360) alpha = 0;
double angle = Math.toRadians(alpha);
int offsetX = (int) (i + (float)(i * Math.cos(angle)));
int offsetY = (int) (i - (float)(i * Math.sin(angle)));
latestPoint[0]= new Point(offsetX, offsetY);
for (int x=POINT_ARRAY_SIZE-1; x > 0; x--) {
latestPoint[x] = latestPoint[x-1];
}
int lines = 0;
for (int x = 0; x < POINT_ARRAY_SIZE; x++) {
Point point = latestPoint[x];
if (point != null) {
canvas.drawLine(i, i, point.x, point.y, latestPaint[x]);
}
}
lines = 0;
for (Point p : latestPoint) if (p != null) lines++;
boolean debug = false;
if (debug) {
StringBuilder sb = new StringBuilder(" >> ");
for (Point p : latestPoint) {
if (p != null) sb.append(" (" + p.x + "x" + p.y + ")");
}
Log.d(LOG, sb.toString());
// " - R:" + r + ", i=" + i +
// " - Size: " + width + "x" + height +
// " - Angle: " + angle +
// " - Offset: " + offsetX + "," + offsetY);
}
}
}
in your activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#android:color/black">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start"
android:onClick="startAniamtion"/>
<frusso.radartest.RadarView
android:id="#+id/radarView"
android:layout_width="240dp"
android:layout_height="240dp"
android:layout_gravity="center_horizontal"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stop"
android:onClick="stopAnimation"/>
Activity.java
public class MainActivity extends Activity {
RadarView mRadarView = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRadarView = (RadarView) findViewById(R.id.radarView);
mRadarView.setShowCircles(true);
}
public void stopAnimation(View view) {
if (mRadarView != null) mRadarView.stopAnimation();
}
public void startAnimation(View view) {
if (mRadarView != null) mRadarView.startAnimation();
}
}
Hope this will guide you for your requirement.
My approach would be to have one static image of the radar and another of the dot (if you wanted a custom one). I'd have 2 main threads, the game loop and one that moves the dot on your radar image based on your position.
"I am monitoring certain distances" ~ What does that mean?
To make a radar create a class that extends ImageView. Override onDraw(Canvas canvas) and set the image resource to a radar background.
#Override
public void onDraw(Canvas canvas) {
//draw background
super.onDraw(canvas);
for(PointF p : points)
{
//draw each point as an image. Maybe, translate by width/2 and height/2
}
}