Home | History | Annotate | Download | only in views
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.fmradio.views;
     18 
     19 import android.content.Context;
     20 import android.graphics.Canvas;
     21 import android.graphics.Color;
     22 import android.graphics.Paint;
     23 import android.graphics.RectF;
     24 import android.os.Handler;
     25 import android.util.AttributeSet;
     26 import android.view.View;
     27 
     28 /**
     29  * The view used to display the visualizer
     30  */
     31 public final class FmVisualizerView extends View {
     32 
     33     private final Handler mHandler = new Handler();
     34 
     35     private Paint mPaint = new Paint();
     36 
     37     private float mColumnPadding = 3f;
     38 
     39     private boolean mAnimate = false;
     40 
     41     private int mFrequency = 100;
     42 
     43     private static final int COLUME_PADDING_COUNTS = 2;
     44 
     45     private static final int COLUME_COUNTS = 3;
     46 
     47     private static final float[] DEFALT_VISUALIZER_LEVEL = new float[] {
     48             +0.4f, 1f, -0.2f
     49     };
     50 
     51     private float[] mPrevLevels = DEFALT_VISUALIZER_LEVEL;
     52 
     53     /**
     54      * Constructor method
     55      *
     56      * @param context The context instance
     57      * @param attrs The attribute set for this view
     58      * @param defStyleAttr The default style for this view
     59      */
     60     public FmVisualizerView(Context context, AttributeSet attrs, int defStyleAttr) {
     61         super(context, attrs, defStyleAttr);
     62         init();
     63     }
     64 
     65     /**
     66      * Constructor method
     67      *
     68      * @param context The context instance
     69      * @param attrs The attribute set for this view
     70      */
     71     public FmVisualizerView(Context context, AttributeSet attrs) {
     72         super(context, attrs);
     73         init();
     74     }
     75 
     76     /**
     77      * Constructor method
     78      *
     79      * @param context The context instance
     80      */
     81     public FmVisualizerView(Context context) {
     82         super(context);
     83         init();
     84     }
     85 
     86     private void init() {
     87         mPaint.setColor(0xff607d8b);
     88         mPaint.setAntiAlias(true);
     89         mPaint.setStrokeWidth(0.3f);
     90         mPaint.setStrokeCap(Paint.Cap.ROUND);
     91         mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
     92         mAnimate = false;
     93     }
     94 
     95     /**
     96      * Set the padding between visualizer columns
     97      *
     98      * @param padding The padding between visualizer columns
     99      */
    100     public void setColumnPadding(int padding) {
    101         mColumnPadding = padding;
    102     }
    103 
    104     /**
    105      * Start the animation
    106      */
    107     public void startAnimation() {
    108         mAnimate = true;
    109     }
    110 
    111     /**
    112      * Start the animation
    113      */
    114     public void stopAnimation() {
    115         mAnimate = false;
    116     }
    117 
    118     /**
    119      * Whether currently is under animation
    120      *
    121      * @return The animation state
    122      */
    123     public boolean isAnimated() {
    124         return mAnimate;
    125     }
    126 
    127     /**
    128      * Set the animation frequency
    129      *
    130      * @param freguency The specify animation frequency to set
    131      */
    132     public void setAnimateFrequency(int freguency) {
    133         mFrequency = freguency;
    134     }
    135 
    136     /**
    137      * Defined to re-freash the view
    138      */
    139     private final Runnable mRefreashRunnable = new Runnable() {
    140         public void run() {
    141             FmVisualizerView.this.invalidate();
    142         }
    143     };
    144 
    145     @Override
    146     protected void onDraw(Canvas canvas) {
    147         super.onDraw(canvas);
    148         canvas.save();
    149         canvas.drawColor(Color.TRANSPARENT);
    150         int viewHeight = getHeight();
    151         int viewWidth = getWidth();
    152         int paddingLeft = getPaddingLeft();
    153         int paddingRight = getPaddingRight();
    154         int paddingTop = getPaddingTop();
    155         int paddingBottom = getPaddingBottom();
    156         float colWidth = ((float) (viewWidth - paddingLeft - paddingRight - COLUME_PADDING_COUNTS
    157                 * mColumnPadding))
    158                 / COLUME_COUNTS;
    159         float colHeight = (float) (viewHeight - paddingBottom - paddingTop);
    160 
    161         float levels[] = new float[COLUME_COUNTS];
    162         if (!mAnimate) {
    163             levels = DEFALT_VISUALIZER_LEVEL;
    164         } else {
    165             levels = generate(COLUME_COUNTS);
    166         }
    167         for (int i = 0; i < COLUME_COUNTS; i++) {
    168             float left = paddingLeft + i * (mColumnPadding + colWidth);
    169             float right = left + colWidth;
    170             float startY = paddingTop + colHeight / 2;
    171             startY -= colHeight / 2 * levels[i];
    172             if (startY < paddingTop) {
    173                 startY = paddingTop;
    174             }
    175             float bottom = viewHeight - paddingBottom;
    176             RectF rect = new RectF(left, startY, right, bottom);
    177             canvas.drawRect(rect, mPaint);
    178         }
    179         mHandler.removeCallbacks(mRefreashRunnable);
    180         mHandler.postDelayed(mRefreashRunnable, mFrequency);
    181     }
    182 
    183     /**
    184      * Used to generate out the float array with specify array count
    185      *
    186      * @param count The array count
    187      * @return A float array with specify array count
    188      */
    189     private float[] generate(int count) {
    190         if (count <= 0) {
    191             return null;
    192         }
    193         int[] sign = {
    194                 -1, 1
    195         };
    196         float[] result = new float[count];
    197         for (int i = 0; i < count; i++) {
    198             while (true) {
    199                 result[i] = (float) Math.random() * 1f
    200                         * (float) sign[(int) (Math.random() * 2)];
    201                 if (Math.abs(mPrevLevels[i] - result[i]) < 0.3f & result[i] > -0.3f) {
    202                     break;
    203                 }
    204             }
    205         }
    206         mPrevLevels = result;
    207         return result;
    208     }
    209 }
    210