In some music applications, often show the ups and downs of the ripple information, these ripple image to convey the voice information, can enhance the user experience, then how to achieve it? You can use the visualizer class to get the currently playing sound information and draw it on the canvas, using a ripple display. Let me explain how to use it.
Main
(1) The way to extract ripple information from the visualizer class.
(2) Application of dynamic rights Management method.
(3) Separating the display and logic of the custom view.
1. Basic Preparation
Android 6.0 introduces dynamic rights Management, in this project, will use the system audio information, so the rights management into this project, reference. The Gradle configuration introduces a lambda expression for reference.
Page layout, using a custom Ripple view control.
<!--Ripple View-->
<me.chunyu.spike.wcl_visualizer_demo.visualizers.waveformview
android:id= "@+id/ Main_wv_waveform "
android:layout_width=" match_parent "
android:layout_height=" match_parent "/>"
Effect
2. Home logic
Add dynamic rights Management to obtain the audio permissions that are required for the application when the page is started. The
Rendererfactory factory class creates a wavy drawing class Simplewaveformrender. The
Startvisualiser method gets the audio information for the current music playback.
Note that the page closes and the Visualiser class is released when OnPause.
public class Mainactivity extends Appcompatactivity {private static final int capture_size = 256;//get this data to display privat
e static final int request_code = 0; Permissions private static final string[] PERMISSIONS = new string[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.MOD
Ify_audio_settings}; @Bind (r.id.main_wv_waveform) Waveformview mwvwaveform; Ripple view Private Visualizer mvisualizer;
Audio Visualization class @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Butterknife.bind (this);
Rendererfactory rendererfactory = new Rendererfactory (); Mwvwaveform.setrenderer (Rendererfactory.createsimplewaveformrender, Contextcompat.getcolor (this,
r.color.colorprimary), color.white);
} @Override protected void Onresume () {super.onresume ();
Permissionschecker Checker = new Permissionschecker (this); if (Checker.lakespermissions (PERMISSIONS)) {Permissionsactivity.startactivityforresult (this, Request_code, PERMISSIONS);
else {startvisualiser ();}} @Override protected void Onactivityresult (int requestcode, int resultcode, Intent data) {Super.onactivityresult (
Requestcode, ResultCode, data);
if (Requestcode = = Request_code && ResultCode = = permissionsactivity.permissions_denied) {finish ();}} Set the audio line private void Startvisualiser () {Mvisualizer = new Visualizer (0);//Initialize Mvisualizer.setdatacapturelistener (new V Isualizer. Ondatacapturelistener () {@Override public void onwaveformdatacapture (Visualizer visualizer, byte[] waveform, int Samplingrate) {if (mwvwaveform!= null) {mwvwaveform.setwaveform (waveform);}} @Override public void Onfftdatacapture (V
Isualizer Visualizer, byte[] FFT, int samplingrate) {}}, Visualizer.getmaxcapturerate (), True, false);
Mvisualizer.setcapturesize (capture_size);
Mvisualizer.setenabled (TRUE); }//Free @Override protected void OnPause () {if (Mvisualizer!= null) {mvisualizer.setenabled (false); mvisualizer.release
();
} super.onpause (); }
}
Visualizer class
New Visualizer (0), initializing; Setcapturesize, obtain the ripple quantity; SetEnabled, start listening;
Setdatacapturelistener, the first parameter is a callback, using Waveformdata or fftdata; The second one is the renewal rate; The third is to judge the use of waveformdata; The fourth is to judge the use of Fftdata, and the third \ Four are all related to the return value of the callback.
3. Corrugated View
Page frame, separating display and logic, using interface rendering, input canvas canvas and ripple waveform.
/** * Audio Ripple View * <p> * Created by Wangchenlong on 16/2/11. */public class Waveformview Exte NDS View {private waveformrenderer mrenderer;//Draw class private byte[] mwaveform;//Ripple Shape public waveformview (context Contex T) {super (context);} public Waveformview (context, AttributeSet attrs) {Super (context, attrs);} public waveform View (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); @TargetApi Waveformview (context, AttributeSet attrs, int defstyleattr, int defstyleres) {Super (context, Attrs, defstyleattr
, defstyleres);
public void Setrenderer (Waveformrenderer renderer) {mrenderer = renderer;} public void Setwaveform (byte[] waveform) { Mwaveform = arrays.copyof (waveform, waveform.length); Array copy invalidate (); After you set the ripple, you need to redraw the} @Override protected void OnDraw (Canvas Canvas) {Super.ondraw (Canvas); if (mrenderer!= null) {Mrendere
R.render (canvas, mwaveform); }
}
}
Array copy arrays.copyof (), redraw the page invalidate () after the ripple is set.
4. Ripple Logic
Core part renderwaveform, Render Ripple.
Divides the page into the grid style, according to the ripple value, draws the curve; Without ripple, draw center horizontal line.
/** * Ripple Rendering logic * <p> * Created by Wangchenlong on 16/2/12. * * Public class Simplewaveformrenderer implements Waveformrenderer {private static final int y_factor = 0xFF;//2 of 8 times =
256 private static final float half_factor = 0.5f;
@ColorInt private final int mbackgroundcolor;
Private final Paint Mforegroundpaint;
Private final Path Mwaveformpath;
Private Simplewaveformrenderer (@ColorInt int backgroundcolor, Paint foregroundpaint, Path waveformpath) {
Mbackgroundcolor = BackgroundColor;
Mforegroundpaint = Foregroundpaint;
Mwaveformpath = Waveformpath; public static Simplewaveformrenderer newinstance (@ColorInt int backgroundcolor, @ColorInt int foregroundcolour) {Paint
Paint = new paint ();
Paint.setcolor (Foregroundcolour); Paint.setantialias (TRUE); Anti-aliasing paint.setstrokewidth (8.0f); Set width Paint.setstyle (Paint.Style.STROKE);
Fill path Waveformpath = new Path ();
return new Simplewaveformrenderer (backgroundcolor, Paint, Waveformpath); @Override public void render (Canvas Canvas, byte[] waveform) {Canvas.drawcolor (mbackgroundcolor); float width = canvas.getwidth (); Float height = canvas.getheight (
);
Mwaveformpath.reset (); No data if (waveform!= null) {//Draw waveform Renderwaveform (waveform, width, height);} else {//Draw line Renderblank (width, heigh
T);
} canvas.drawpath (Mwaveformpath, mforegroundpaint); } private void Renderwaveform (byte[] waveform, float width, float height) {float xincrement = width/(float) (WAVEFORM.L Ength); Horizontal block number float yincrement = height/y_factor; Vertical block Number int halfheight = (int) (height * half_factor);
Center position mwaveformpath.moveto (0, halfheight); for (int i = 1; i < waveform.length ++i) {float yposition = Waveform[i] > 0? height-(yincrement * waveform[i])
:-(Yincrement * waveform[i]);
Mwaveformpath.lineto (Xincrement * i, yposition); } mwaveformpath.lineto (width, halfheight); Last point, horizontally centered}//center draw a straight line private void Renderblank (float width, float height) {int y = (int) (height * half_factor); mWa
Veformpath.moveto (0, y); MwavefOrmpath.lineto (width, y); }
}
Draws a moving moveto, drawing a straight line LineTo.
Animation effects
By drawing ripples, you can draw some continuous data in a similar way, showing more visually and enhancing the user experience.