/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.fmradio.views; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.os.Handler; import android.util.AttributeSet; import android.view.View; /** * The view used to display the visualizer */ public final class FmVisualizerView extends View { private final Handler mHandler = new Handler(); private Paint mPaint = new Paint(); private float mColumnPadding = 3f; private boolean mAnimate = false; private int mFrequency = 100; private static final int COLUME_PADDING_COUNTS = 2; private static final int COLUME_COUNTS = 3; private static final float[] DEFALT_VISUALIZER_LEVEL = new float[] { +0.4f, 1f, -0.2f }; private float[] mPrevLevels = DEFALT_VISUALIZER_LEVEL; /** * Constructor method * * @param context The context instance * @param attrs The attribute set for this view * @param defStyleAttr The default style for this view */ public FmVisualizerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } /** * Constructor method * * @param context The context instance * @param attrs The attribute set for this view */ public FmVisualizerView(Context context, AttributeSet attrs) { super(context, attrs); init(); } /** * Constructor method * * @param context The context instance */ public FmVisualizerView(Context context) { super(context); init(); } private void init() { mPaint.setColor(0xff607d8b); mPaint.setAntiAlias(true); mPaint.setStrokeWidth(0.3f); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mAnimate = false; } /** * Set the padding between visualizer columns * * @param padding The padding between visualizer columns */ public void setColumnPadding(int padding) { mColumnPadding = padding; } /** * Start the animation */ public void startAnimation() { mAnimate = true; } /** * Start the animation */ public void stopAnimation() { mAnimate = false; } /** * Whether currently is under animation * * @return The animation state */ public boolean isAnimated() { return mAnimate; } /** * Set the animation frequency * * @param freguency The specify animation frequency to set */ public void setAnimateFrequency(int freguency) { mFrequency = freguency; } /** * Defined to re-freash the view */ private final Runnable mRefreashRunnable = new Runnable() { public void run() { FmVisualizerView.this.invalidate(); } }; @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.drawColor(Color.TRANSPARENT); int viewHeight = getHeight(); int viewWidth = getWidth(); int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingRight(); int paddingTop = getPaddingTop(); int paddingBottom = getPaddingBottom(); float colWidth = ((float) (viewWidth - paddingLeft - paddingRight - COLUME_PADDING_COUNTS * mColumnPadding)) / COLUME_COUNTS; float colHeight = (float) (viewHeight - paddingBottom - paddingTop); float levels[] = new float[COLUME_COUNTS]; if (!mAnimate) { levels = DEFALT_VISUALIZER_LEVEL; } else { levels = generate(COLUME_COUNTS); } for (int i = 0; i < COLUME_COUNTS; i++) { float left = paddingLeft + i * (mColumnPadding + colWidth); float right = left + colWidth; float startY = paddingTop + colHeight / 2; startY -= colHeight / 2 * levels[i]; if (startY < paddingTop) { startY = paddingTop; } float bottom = viewHeight - paddingBottom; RectF rect = new RectF(left, startY, right, bottom); canvas.drawRect(rect, mPaint); } mHandler.removeCallbacks(mRefreashRunnable); mHandler.postDelayed(mRefreashRunnable, mFrequency); } /** * Used to generate out the float array with specify array count * * @param count The array count * @return A float array with specify array count */ private float[] generate(int count) { if (count <= 0) { return null; } int[] sign = { -1, 1 }; float[] result = new float[count]; for (int i = 0; i < count; i++) { while (true) { result[i] = (float) Math.random() * 1f * (float) sign[(int) (Math.random() * 2)]; if (Math.abs(mPrevLevels[i] - result[i]) < 0.3f & result[i] > -0.3f) { break; } } } mPrevLevels = result; return result; } }