├── settings.gradle ├── .gitignore └── app ├── libs └── glide-3.6.1.jar ├── src └── main │ ├── res │ ├── drawable │ │ └── logo.png │ ├── raw │ │ ├── bubble_mould.png │ │ ├── sakura_leave.png │ │ └── faq │ ├── values │ │ ├── colors.xml │ │ ├── attrs.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── arrays.xml │ ├── xml │ │ ├── livesetting.xml │ │ ├── provider_paths.xml │ │ ├── duang.xml │ │ ├── circle_setting.xml │ │ └── setting.xml │ ├── layout │ │ ├── color_picker.xml │ │ ├── seekbar_preference.xml │ │ └── seekbar_preference_material.xml │ ├── values-v19 │ │ └── styles.xml │ ├── values-v20 │ │ └── styles.xml │ └── values-v21 │ │ └── styles.xml │ ├── java │ └── com │ │ └── moe │ │ └── LiveVisualizer │ │ ├── internal │ │ ├── OnColorSizeChangedListener.java │ │ ├── ShadowDrawable.java │ │ ├── VideoThread.java │ │ ├── VisualizerThread.java │ │ └── ImageDraw.java │ │ ├── duang │ │ ├── Hanabi.java │ │ ├── MeteorShower.java │ │ ├── Image.java │ │ ├── Rain.java │ │ ├── Sakura.java │ │ ├── Bubble.java │ │ ├── Duang.java │ │ ├── Graph.java │ │ ├── Snow.java │ │ └── Engine.java │ │ ├── inter │ │ └── Draw.java │ │ ├── adapter │ │ └── ColorAdapter.java │ │ ├── utils │ │ ├── ColorList.java │ │ ├── BitmapUtils.java │ │ └── PreferencesUtils.java │ │ ├── service │ │ ├── CircleSwitch.java │ │ └── SharedPreferences.java │ │ ├── app │ │ ├── ColorDialog.java │ │ └── Application.java │ │ ├── activity │ │ ├── CrashActivity.java │ │ ├── CropActivity.java │ │ ├── SettingActivity.java │ │ └── ColorListActivity.java │ │ ├── preference │ │ ├── ColorPickerPreference.java │ │ └── SeekBarPreference.java │ │ ├── widget │ │ └── PopupLayout.java │ │ ├── draw │ │ ├── line │ │ │ ├── BlockBreakerDraw.java │ │ │ ├── RadialDraw.java │ │ │ ├── SquareDraw.java │ │ │ ├── YamaLineDraw.java │ │ │ ├── PopCircleDraw.java │ │ │ └── LineChartDraw.java │ │ ├── circle │ │ │ ├── CircleDisperseDraw.java │ │ │ ├── UnKnow3.java │ │ │ ├── UnKnow1.java │ │ │ ├── CircleRadialDraw.java │ │ │ ├── UnKnow2.java │ │ │ ├── HeartDraw.java │ │ │ ├── CircleTriangleDraw.java │ │ │ ├── CenterRadialDraw.java │ │ │ ├── RippleDraw.java │ │ │ └── RingDraw.java │ │ ├── CircleDraw.java │ │ ├── LineDraw.java │ │ └── Draw.java │ │ ├── database │ │ └── MoeData.java │ │ └── fragment │ │ ├── DuangSettingFragment.java │ │ └── CircleSettingFragment.java │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | gen/ 3 | libs/*/*.so 4 | 5 | -------------------------------------------------------------------------------- /app/libs/glide-3.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dorobonneko/wallpaper/HEAD/app/libs/glide-3.6.1.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dorobonneko/wallpaper/HEAD/app/src/main/res/drawable/logo.png -------------------------------------------------------------------------------- /app/src/main/res/raw/bubble_mould.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dorobonneko/wallpaper/HEAD/app/src/main/res/raw/bubble_mould.png -------------------------------------------------------------------------------- /app/src/main/res/raw/sakura_leave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dorobonneko/wallpaper/HEAD/app/src/main/res/raw/sakura_leave.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #50000000 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/xml/livesetting.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 壁纸频谱 5 | Hello world! 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/internal/OnColorSizeChangedListener.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.internal; 2 | 3 | public abstract interface OnColorSizeChangedListener 4 | { 5 | void onColorSizeChanged(); 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/color_picker.xml: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values-v19/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values-v20/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/xml/provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/duang/Hanabi.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.duang; 2 | import android.util.DisplayMetrics; 3 | import android.graphics.Canvas; 4 | import java.util.Random; 5 | 6 | public class Hanabi extends Duang 7 | { 8 | 9 | 10 | @Override 11 | public void draw(Canvas canvas) 12 | { 13 | // TODO: Implement this method 14 | } 15 | 16 | @Override 17 | public void random(Random random) 18 | { 19 | // TODO: Implement this method 20 | } 21 | 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/duang/MeteorShower.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.duang; 2 | import android.util.DisplayMetrics; 3 | import android.graphics.Canvas; 4 | import java.util.Random; 5 | 6 | public class MeteorShower extends Duang 7 | { 8 | 9 | 10 | @Override 11 | public void draw(Canvas canvas) 12 | { 13 | // TODO: Implement this method 14 | } 15 | 16 | @Override 17 | public void random(Random random) 18 | { 19 | // TODO: Implement this method 20 | } 21 | 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\tools\adt-bundle-windows-x86_64-20131030\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/internal/ShadowDrawable.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.internal; 2 | import android.graphics.drawable.Drawable; 3 | import android.graphics.Canvas; 4 | import android.graphics.ColorFilter; 5 | import android.graphics.PixelFormat; 6 | import android.graphics.Paint; 7 | import android.graphics.Rect; 8 | 9 | public class ShadowDrawable extends Drawable 10 | { 11 | private Paint paint=new Paint(); 12 | public ShadowDrawable(){ 13 | paint.setColor(0xffffffff); 14 | paint.setShadowLayer(15,0,15,0xff000000); 15 | } 16 | @Override 17 | public void draw(Canvas p1) 18 | { 19 | //p1.drawColor(0xffffffff); 20 | } 21 | 22 | @Override 23 | public void setAlpha(int p1) 24 | { 25 | paint.setAlpha(p1); 26 | } 27 | 28 | @Override 29 | public void setColorFilter(ColorFilter p1) 30 | { 31 | paint.setColorFilter(p1); 32 | } 33 | 34 | @Override 35 | public int getOpacity() 36 | { 37 | // TODO: Implement this method 38 | return PixelFormat.TRANSLUCENT; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.0" 6 | 7 | defaultConfig { 8 | applicationId "com.moe.LiveVisualizer" 9 | minSdkVersion 15 10 | targetSdkVersion 27 11 | versionCode 81 12 | versionName "4.3" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | //compile 'com.plattysoft.leonids:LeonidsLib:+' 24 | //compile 'com.tencent.bugly:crashreport:+' 25 | //compile 'com.github.bumptech.glide:gifdecoder:+' 26 | //compile 'pl.droidsonroids.gif:android-gif-drawable:+' 27 | //compile 'com.android.support:support-core-utils:24+' 28 | //compile 'com.android.support:palette-v7:25+' 29 | //compile 'com.android.support:support-vector-drawable:25+' 30 | //compile 'com.android.support:support-media-compat:25+' 31 | compile fileTree(dir: 'libs', include: ['*.jar']) 32 | } 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 17 | 21 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/inter/Draw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.inter; 2 | import android.graphics.Canvas; 3 | import android.graphics.Shader; 4 | import com.moe.LiveVisualizer.service.LiveWallpaper; 5 | import android.graphics.Matrix; 6 | import android.graphics.Paint; 7 | 8 | public interface Draw 9 | { 10 | 11 | boolean isFinalized(); 12 | 13 | void finalized(); 14 | 15 | void draw(Canvas canvas); 16 | void onDraw(Canvas canvas,int color_mode)throws NullPointerException; 17 | void drawGraph(double[] buffer,Canvas canvas,int color_mode,boolean useMode)throws NullPointerException; 18 | double[] getFft(); 19 | byte[] getWave(); 20 | //float getDownSpeed(); 21 | 22 | LiveWallpaper.WallpaperEngine getEngine(); 23 | void onBorderWidthChanged(int width); 24 | void onBorderHeightChanged(int height); 25 | void onSpaceWidthChanged(int space); 26 | void onDrawHeightChanged(float height); 27 | int size(); 28 | int getColor(); 29 | //void setShader(Shader shader); 30 | Shader getShader(); 31 | void setRound(boolean round); 32 | //void setCutImage(boolean cut); 33 | //Matrix getCenterScale(); 34 | void setOffsetX(int x); 35 | void setOffsetY(int y); 36 | void notifySizeChanged(); 37 | float getInterpolator(float interpolator); 38 | void checkMode(int mode,Paint paint); 39 | void setAntialias(boolean antialias); 40 | void setNum(int num); 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/adapter/ColorAdapter.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.adapter; 2 | import android.widget.BaseAdapter; 3 | import android.view.ViewGroup; 4 | import android.view.View; 5 | import com.moe.LiveVisualizer.utils.ColorList; 6 | import android.view.LayoutInflater; 7 | import android.widget.TextView; 8 | import android.graphics.Color; 9 | 10 | public class ColorAdapter extends BaseAdapter 11 | { 12 | private ColorList list; 13 | public ColorAdapter(ColorList list){ 14 | this.list=list; 15 | } 16 | @Override 17 | public int getCount() 18 | { 19 | // TODO: Implement this method 20 | return list.size(); 21 | } 22 | 23 | @Override 24 | public Object getItem(int p1) 25 | { 26 | return list.get(p1); 27 | } 28 | 29 | @Override 30 | public long getItemId(int p1) 31 | { 32 | return p1; 33 | } 34 | 35 | @Override 36 | public View getView(int p1, View p2, ViewGroup p3) 37 | { 38 | View view; 39 | if(p2!=null) 40 | view=p2; 41 | else 42 | view=LayoutInflater.from(p3.getContext()).inflate(android.R.layout.simple_list_item_1,p3,false); 43 | TextView text=(TextView) view; 44 | text.setTextColor(list.get(p1)); 45 | final float[] hsv=new float[3]; 46 | Color.colorToHSV(list.get(p1),hsv); 47 | text.setText("HSV:"+hsv[0]+" "+hsv[1]+" "+hsv[2]+" #"+Integer.toHexString(list.get(p1)).toUpperCase()); 48 | return view; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/utils/ColorList.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.utils; 2 | import java.util.List; 3 | import java.util.Collection; 4 | import java.util.Iterator; 5 | import java.util.ListIterator; 6 | import java.util.Set; 7 | import java.util.Arrays; 8 | 9 | public class ColorList 10 | { 11 | private int[] buffer; 12 | private int capacity=7; 13 | private int size; 14 | public ColorList(){ 15 | buffer=new int[capacity]; 16 | } 17 | 18 | public synchronized int getRandom() 19 | { 20 | return get((int)(Math.random()*size)); 21 | } 22 | public synchronized int size() 23 | { 24 | return size; 25 | } 26 | 27 | public synchronized boolean isEmpty() 28 | { 29 | return size==0; 30 | } 31 | 32 | public synchronized int[] toArray() 33 | { 34 | return Arrays.copyOf(buffer,size); 35 | } 36 | public synchronized int get(int index){ 37 | return buffer[index]; 38 | } 39 | public synchronized boolean add(int p1) 40 | { 41 | buffer[size]=p1; 42 | size++; 43 | trim(); 44 | return true; 45 | } 46 | 47 | public synchronized boolean remove(int index) 48 | { 49 | for(;index=buffer.length-1){ 63 | int[] src=buffer; 64 | buffer=new int[src.length+(int)(capacity*0.5f)]; 65 | System.arraycopy(src,0,buffer,0,size); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/res/xml/duang.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 16 | 22 | 28 | 34 | 40 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/service/CircleSwitch.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.service; 2 | import android.service.quicksettings.TileService; 3 | import android.content.SharedPreferences; 4 | import android.service.quicksettings.Tile; 5 | 6 | public class CircleSwitch extends TileService 7 | { 8 | private SharedPreferences moe; 9 | 10 | @Override 11 | public void onCreate() 12 | { 13 | super.onCreate(); 14 | moe=getSharedPreferences("moe",0); 15 | } 16 | 17 | @Override 18 | public void onTileAdded() 19 | { 20 | Tile tile=getQsTile(); 21 | if(tile!=null){ 22 | tile.setLabel(moe.getBoolean("circleSwitch",true)?"旋转开启":"旋转关闭"); 23 | tile.setState(Tile.STATE_ACTIVE); 24 | tile.updateTile(); 25 | } 26 | } 27 | 28 | @Override 29 | public void onTileRemoved() 30 | { 31 | Tile tile=getQsTile(); 32 | if(tile!=null){ 33 | tile.setLabel(moe.getBoolean("circleSwitch",true)?"旋转开启":"旋转关闭"); 34 | tile.setState(Tile.STATE_INACTIVE); 35 | tile.updateTile(); 36 | } 37 | } 38 | 39 | @Override 40 | public void onClick() 41 | { 42 | moe.edit().putBoolean("circleSwitch",!moe.getBoolean("circleSwitch",true)).commit(); 43 | Tile tile=getQsTile(); 44 | if(tile!=null){ 45 | tile.setLabel(moe.getBoolean("circleSwitch",true)?"旋转开启":"旋转关闭"); 46 | tile.setState(Tile.STATE_ACTIVE); 47 | tile.updateTile(); 48 | } 49 | } 50 | 51 | @Override 52 | public void onStartListening() 53 | { 54 | onTileAdded(); 55 | } 56 | 57 | @Override 58 | public void onStopListening() 59 | { 60 | // TODO: Implement this method 61 | super.onStopListening(); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/app/ColorDialog.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.app; 2 | import android.app.DialogFragment; 3 | import android.view.View; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | import android.os.Bundle; 7 | import com.moe.LiveVisualizer.widget.ColorPickerView; 8 | import android.view.WindowManager; 9 | import android.view.Window; 10 | import android.app.Dialog; 11 | import com.moe.LiveVisualizer.R; 12 | 13 | public class ColorDialog extends DialogFragment implements ColorPickerView.OnColorCheckedListener 14 | { 15 | public ColorPickerView.OnColorCheckedListener l; 16 | @Override 17 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 18 | { 19 | // TODO: Implement this method 20 | return inflater.inflate(R.layout.color_picker,container,false); 21 | } 22 | 23 | @Override 24 | public void onViewCreated(View view, Bundle savedInstanceState) 25 | { 26 | ColorPickerView picker=(ColorPickerView) view; 27 | picker.setOnColorCheckedListener(this); 28 | super.onViewCreated(view, savedInstanceState); 29 | } 30 | 31 | @Override 32 | public void onColorChecked(int color) 33 | { 34 | if(l!=null)l.onColorChecked(color); 35 | } 36 | 37 | @Override 38 | public Dialog onCreateDialog(Bundle savedInstanceState) 39 | { 40 | // TODO: Implement this method 41 | Dialog d= super.onCreateDialog(savedInstanceState); 42 | d.getWindow().requestFeature(Window.FEATURE_NO_TITLE); 43 | 44 | return d; 45 | } 46 | 47 | 48 | public void setOnColorCheckedListener(ColorPickerView.OnColorCheckedListener l){ 49 | this.l=l; 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/res/xml/circle_setting.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 17 | 22 | 27 | 32 | 37 | 38 | 43 | 49 | 53 | 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/duang/Image.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.duang; 2 | import java.util.Random; 3 | import android.graphics.Canvas; 4 | import android.graphics.Matrix; 5 | import android.util.DisplayMetrics; 6 | import android.graphics.Bitmap; 7 | 8 | public class Image extends Duang 9 | { 10 | private Matrix matrix; 11 | private float speed,wind; 12 | public Image(){ 13 | matrix=new Matrix(); 14 | } 15 | 16 | @Override 17 | public void draw(Canvas canvas) 18 | { 19 | if(getOffsetX()>getMaxWidth()+getSize()||getOffsetY()>getMaxHeight()+getSize()){ 20 | matrix.postTranslate(-getOffsetX(),-getOffsetY()); 21 | setOffsetX(getRandom().nextInt((int)(getMaxWidth()-getSize()))); 22 | setOffsetY(-getSize()); 23 | matrix.postTranslate(getOffsetX(),getOffsetY()); 24 | }else if(getOffsetY()>-getSize()){ 25 | setOffsetX(getOffsetX()+wind); 26 | setOffsetY(getOffsetY()+speed); 27 | matrix.postTranslate(wind,speed); 28 | canvas.drawBitmap(getEngine().getBuffer(),matrix,null); 29 | }else { 30 | setOffsetY(getOffsetY()+speed); 31 | matrix.postTranslate(0,speed); 32 | } 33 | } 34 | 35 | @Override 36 | public void random(Random random) 37 | { 38 | setOffsetX(random.nextInt((int)(getMaxWidth()-getSize()))); 39 | if(isFirst()) 40 | setOffsetY(-random.nextInt(getMaxHeight())); 41 | else 42 | setOffsetY(-getSize()); 43 | speed=getSize()/getMaxSize()*getSpeed()/5+1; 44 | wind=random.nextFloat()*getWind(); 45 | Bitmap bitmap=getEngine().getBuffer(); 46 | if(bitmap!=null){ 47 | float scale=getSize()/bitmap.getWidth(); 48 | matrix.postScale(scale,scale); 49 | }matrix.postTranslate(getOffsetX(),getOffsetY()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/activity/CrashActivity.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.activity; 2 | import android.app.Activity; 3 | import android.os.Bundle; 4 | import android.view.Menu; 5 | import android.view.MenuItem; 6 | import android.widget.TextView; 7 | import android.content.Intent; 8 | import android.text.method.ArrowKeyMovementMethod; 9 | import android.net.Uri; 10 | import android.content.ClipboardManager; 11 | import android.content.pm.PackageManager.NameNotFoundException; 12 | import android.content.pm.PackageManager; 13 | import android.os.Build; 14 | 15 | public class CrashActivity extends Activity 16 | { 17 | StringBuffer sb; 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) 20 | { 21 | // TODO: Implement this method 22 | super.onCreate(savedInstanceState); 23 | TextView tv=new TextView(this); 24 | tv.setText(getIntent().getStringExtra(Intent.EXTRA_TEXT)); 25 | sb= new StringBuffer(tv.getText()); 26 | tv.setMovementMethod(new ArrowKeyMovementMethod()); 27 | tv.setFitsSystemWindows(true); 28 | tv.setTextColor(0xffffffff); 29 | setContentView(tv); 30 | } 31 | 32 | @Override 33 | public boolean onCreateOptionsMenu(Menu menu) 34 | { 35 | MenuItem item=menu.add(0,0,0,"发送给开发者"); 36 | item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); 37 | return true; 38 | } 39 | 40 | @Override 41 | public boolean onOptionsItemSelected(MenuItem item) 42 | { 43 | ((ClipboardManager)getSystemService(CLIPBOARD_SERVICE)).setText(sb.insert(0, "@千羽樱 ").toString()); 44 | Intent intent=new Intent(Intent.ACTION_VIEW); 45 | intent.setData(Uri.parse("https://www.coolapk.com/apk/com.moe.LiveVisualizer")); 46 | startActivity(intent); 47 | return true; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/service/SharedPreferences.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.service; 2 | import android.content.ContentProvider; 3 | import android.net.Uri; 4 | import android.content.ContentValues; 5 | import android.database.Cursor; 6 | import android.database.sqlite.SQLiteOpenHelper; 7 | import android.database.sqlite.SQLiteDatabase; 8 | import com.moe.LiveVisualizer.database.MoeData; 9 | 10 | public class SharedPreferences extends ContentProvider 11 | { 12 | public static final String URI="content://moe/moe"; 13 | private MoeData data; 14 | @Override 15 | public boolean onCreate() 16 | { 17 | data=new MoeData(getContext()); 18 | return true; 19 | } 20 | 21 | @Override 22 | public void shutdown() 23 | { 24 | // TODO: Implement this method 25 | super.shutdown(); 26 | data.close(); 27 | } 28 | 29 | @Override 30 | public Cursor query(Uri p1, String[] p2, String p3, String[] p4, String p5) 31 | { 32 | return data.query(p1.getQueryParameter("key")); 33 | } 34 | 35 | @Override 36 | public String getType(Uri p1) 37 | { 38 | // TODO: Implement this method 39 | return null; 40 | } 41 | 42 | @Override 43 | public Uri insert(Uri p1, ContentValues p2) 44 | { 45 | data.insert(p1.getQueryParameter("key"),p1.getQueryParameter("value")); 46 | return p1; 47 | } 48 | 49 | @Override 50 | public int delete(Uri p1, String p2, String[] p3) 51 | { 52 | getContext().getContentResolver().notifyChange(p1,null); 53 | return data.delete(p1.getQueryParameter("key")); 54 | } 55 | 56 | @Override 57 | public int update(Uri p1, ContentValues p2, String p3, String[] p4) 58 | { 59 | getContext().getContentResolver().notifyChange(p1,null); 60 | return data.update(p1.getQueryParameter("key"),p1.getQueryParameter("value")); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/preference/ColorPickerPreference.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.preference; 2 | import android.preference.Preference; 3 | import android.util.AttributeSet; 4 | import android.content.Context; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.content.SharedPreferences; 8 | import android.app.AlertDialog; 9 | import com.moe.LiveVisualizer.widget.ColorPickerView; 10 | import android.view.LayoutInflater; 11 | import com.moe.LiveVisualizer.R; 12 | import android.preference.ListPreference; 13 | 14 | public class ColorPickerPreference extends Preference implements ColorPickerView.OnColorCheckedListener 15 | { 16 | private AlertDialog dialog; 17 | private SharedPreferences moe; 18 | public ColorPickerPreference(Context context,AttributeSet attrs){ 19 | super(context,attrs); 20 | moe=context.getSharedPreferences("moe",0); 21 | } 22 | 23 | @Override 24 | protected void onBindView(View view) 25 | { 26 | super.onBindView(view); 27 | View v=view.findViewById(android.R.id.widget_frame); 28 | ViewGroup.LayoutParams param=v.getLayoutParams(); 29 | param.width=50; 30 | param.height=50; 31 | v.setLayoutParams(param); 32 | v.setVisibility(v.VISIBLE); 33 | v.setBackgroundColor(moe.getInt("color",0xff39c5bb)); 34 | } 35 | 36 | @Override 37 | protected void onClick() 38 | { 39 | if(dialog==null){ 40 | ColorPickerView picker=(ColorPickerView)LayoutInflater.from(getContext()).inflate(R.layout.color_picker,null); 41 | picker.setOnColorCheckedListener(this); 42 | dialog=new AlertDialog.Builder(getContext()).setView(picker).create(); 43 | } 44 | dialog.show(); 45 | /**/ 46 | } 47 | 48 | @Override 49 | public void onColorChecked(int color) 50 | { 51 | if(shouldPersist()&&callChangeListener(color)){ 52 | persistInt(color); 53 | } 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/duang/Rain.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.duang; 2 | import android.util.DisplayMetrics; 3 | import android.graphics.Canvas; 4 | import java.util.Random; 5 | import android.graphics.Paint; 6 | 7 | public class Rain extends Duang 8 | { 9 | private Paint paint; 10 | private float[] point; 11 | private float speed; 12 | public Rain (){ 13 | point=new float[4]; 14 | paint=new Paint(); 15 | paint.setColor(0xffffffff); 16 | } 17 | 18 | @Override 19 | public void draw(Canvas canvas) 20 | { 21 | if(getOffsetY()>getMaxHeight()||getOffsetX()<=0||getOffsetX()>getMaxWidth()) 22 | { 23 | setOffsetX(getRandom().nextInt(getMaxWidth())); 24 | setOffsetY(-getSize()); 25 | }else if(getOffsetY()<0){ 26 | setOffsetY(getOffsetY()+speed); 27 | }else{ 28 | setOffsetY(getOffsetY()+speed); 29 | canvas.drawLines(point,paint); 30 | } 31 | 32 | } 33 | 34 | @Override 35 | public void random(Random random) 36 | { 37 | paint.setStrokeWidth(random.nextFloat()*2+3); 38 | setOffsetX(random.nextInt(getMaxWidth())); 39 | //setSize(random.nextFloat()*(getMaxSize()-getMinSize())+getMinSize()); 40 | if(isFirst()) 41 | setOffsetY(-random.nextInt(getMaxHeight())); 42 | else 43 | setOffsetY(-getSize()); 44 | speed=getSize()/getMaxSize()*getSpeed()+1; 45 | 46 | } 47 | 48 | @Override 49 | protected void setOffsetX(float offsetX) 50 | { 51 | point[0]=offsetX; 52 | point[2]=offsetX; 53 | } 54 | 55 | @Override 56 | protected void setOffsetY(float offsetY) 57 | { 58 | point[1]=offsetY; 59 | point[3]=getOffsetY()-getSize(); 60 | } 61 | 62 | @Override 63 | public float getOffsetX() 64 | { 65 | // TODO: Implement this method 66 | return point[0]; 67 | } 68 | 69 | @Override 70 | public float getOffsetY() 71 | { 72 | // TODO: Implement this method 73 | return point[1]; 74 | } 75 | 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/widget/PopupLayout.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.widget; 2 | import android.view.ViewGroup; 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.util.TypedValue; 8 | 9 | public class PopupLayout extends ViewGroup 10 | { 11 | private Paint paint; 12 | private int padding=15; 13 | public PopupLayout(Context context){ 14 | super(context); 15 | padding=(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,5,getResources().getDisplayMetrics()); 16 | setPadding(padding,padding,padding,padding); 17 | paint=new Paint(); 18 | paint.setColor(0xffffffff); 19 | paint.setShadowLayer(padding/2.0f,0,0,0xaa000000); 20 | setWillNotDraw(false); 21 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) 22 | setLayerType(View.LAYER_TYPE_SOFTWARE,null); 23 | } 24 | 25 | @Override 26 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 27 | { 28 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 29 | int height=0; 30 | for(int i=0;igetMaxWidth()+getSize()||getOffsetY()>getMaxHeight()+getSize()){ 24 | matrix.postTranslate(-getOffsetX(),-getOffsetY()); 25 | setOffsetX(getRandom().nextInt((int)(getMaxWidth()-getSize()))); 26 | setOffsetY(-getSize()); 27 | matrix.postTranslate(getOffsetX(),getOffsetY()); 28 | }else if(getOffsetY()>-getSize()){ 29 | setOffsetX(getOffsetX()+wind); 30 | setOffsetY(getOffsetY()+speed); 31 | matrix.postTranslate(wind,speed); 32 | canvas.drawBitmap(getEngine().getBuffer(),matrix,null); 33 | }else { 34 | setOffsetY(getOffsetY()+speed); 35 | matrix.postTranslate(0,speed); 36 | } 37 | } 38 | 39 | @Override 40 | public void random(Random random) 41 | { 42 | setOffsetX(random.nextInt((int)(getMaxWidth()-getSize()))); 43 | if(isFirst()) 44 | setOffsetY(-random.nextInt(getMaxHeight())); 45 | else 46 | setOffsetY(-getSize()); 47 | speed=getSize()/getMaxSize()*getSpeed()/5+1; 48 | wind=random.nextFloat()*getWind(); 49 | camera.save(); 50 | camera.rotateX(random.nextInt(360)); 51 | camera.rotateY(random.nextInt(360)); 52 | camera.rotateZ(random.nextInt(360)); 53 | camera.getMatrix(matrix); 54 | camera.restore(); 55 | Bitmap bitmap=getEngine().getBuffer(); 56 | if(bitmap!=null){ 57 | float scale=getSize()/bitmap.getWidth(); 58 | matrix.postScale(scale,scale); 59 | }matrix.postTranslate(getOffsetX(),getOffsetY()); 60 | } 61 | 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/utils/BitmapUtils.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.utils; 2 | import android.graphics.Bitmap; 3 | import android.graphics.Matrix; 4 | import android.renderscript.RenderScript; 5 | import android.renderscript.Allocation; 6 | import android.renderscript.ScriptIntrinsicBlur; 7 | import android.content.Context; 8 | import android.renderscript.Element; 9 | 10 | public class BitmapUtils 11 | { 12 | public static Bitmap scale(Bitmap bit,float scaleX,float scaleY){ 13 | if(bit==null)return null; 14 | Matrix matrix=new Matrix(); 15 | matrix.postScale(scaleX,scaleY); 16 | Bitmap buffer=Bitmap.createBitmap(bit,0,0,bit.getWidth(),bit.getHeight(),matrix,true); 17 | return buffer; 18 | } 19 | public static Bitmap scaleWithSize(Bitmap bit,int width,int height){ 20 | if(bit==null)return null; 21 | float scaleX=((float)width)/bit.getWidth(); 22 | float scaleY=((float)height)/bit.getHeight(); 23 | if(scaleX==1&&scaleY==1)return bit; 24 | return scale(bit,scaleX,scaleY); 25 | } 26 | public static Bitmap blur(Context context,Bitmap bit){ 27 | if(bit==null)return null; 28 | RenderScript rs=RenderScript.create(context); 29 | Bitmap blurredBitmap =BitmapUtils.scaleWithSize(bit,bit.getWidth()/4,bit.getHeight()/4); 30 | 31 | final Allocation input = Allocation.createFromBitmap(rs,blurredBitmap,Allocation.MipmapControl.MIPMAP_FULL,Allocation.USAGE_SHARED); 32 | final Allocation output = Allocation.createTyped(rs,input.getType()); 33 | //(3) 34 | // Load up an instance of the specific script that we want to use. 35 | ScriptIntrinsicBlur scriptIntrinsicBlur = ScriptIntrinsicBlur.create(rs,Element.U8_4(rs)); 36 | //(4) 37 | scriptIntrinsicBlur.setInput(input); 38 | //(5) 39 | // Set the blur radius 40 | scriptIntrinsicBlur.setRadius(25); 41 | //(6) 42 | // Start the ScriptIntrinisicBlur 43 | scriptIntrinsicBlur.forEach(output); 44 | //(7) 45 | // Copy the output to the blurred bitmap 46 | output.copyTo(blurredBitmap); 47 | //(8) 48 | rs.destroy(); 49 | return blurredBitmap; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/line/BlockBreakerDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.line; 2 | import com.moe.LiveVisualizer.draw.LineDraw; 3 | import com.moe.LiveVisualizer.internal.ImageDraw; 4 | import com.moe.LiveVisualizer.service.LiveWallpaper; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.PorterDuff; 8 | import android.graphics.PorterDuffXfermode; 9 | import com.moe.LiveVisualizer.utils.ColorList; 10 | 11 | public class BlockBreakerDraw extends LineDraw 12 | { 13 | private float[] points,breaker; 14 | public BlockBreakerDraw(ImageDraw draw) 15 | { 16 | super(draw); 17 | } 18 | 19 | @Override 20 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) 21 | { 22 | Paint paint=getPaint(); 23 | if (points == null || points.length != size()) 24 | { 25 | points = new float[size()]; 26 | breaker = new float[points.length]; 27 | } 28 | float x=getStartOffset();//起始像素 29 | final float halfWidth=getBorderWidth() / 2; 30 | for (int i=0;i < points.length;i ++) 31 | { 32 | if (useMode) 33 | checkMode(color_mode,paint); 34 | float height=(float)(buffer[i] / (double)Byte.MAX_VALUE * getBorderHeight()); 35 | if (height < points[i]) 36 | points[i]=Math.max(0,points[i]-(points[i]-height)*getInterpolator((points[i]-height)/points[i]*0.99f)); 37 | else if(height>points[i]){ 38 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height*0.79f); 39 | } 40 | if (height < breaker[i]) 41 | breaker[i] =Math.max(0,breaker[i]-(breaker[i]-height)*getInterpolator((breaker[i]-height)/breaker[i]*0.89f)*0.65f); 42 | else if(height>breaker[i]) 43 | breaker[i]=points[i]; 44 | canvas.drawRect(x, getDrawHeight() - points[i], x + getBorderWidth() , getDrawHeight(), paint); 45 | canvas.drawRect(x, getDrawHeight() - breaker[i] - halfWidth, x + getBorderWidth() , getDrawHeight() - breaker[i], paint); 46 | x += getSpaceWidth(); 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/app/Application.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.app; 2 | import java.io.FileOutputStream; 3 | import java.io.FileNotFoundException; 4 | import java.io.IOException; 5 | import java.lang.reflect.Method; 6 | import java.lang.reflect.Proxy; 7 | import android.content.res.Resources; 8 | import java.lang.reflect.InvocationHandler; 9 | import com.moe.LiveVisualizer.R; 10 | import android.content.Intent; 11 | import com.moe.LiveVisualizer.activity.CrashActivity; 12 | import android.content.pm.PackageManager.NameNotFoundException; 13 | import android.content.pm.PackageManager; 14 | import android.os.Build; 15 | 16 | public class Application extends android.app.Application implements Thread.UncaughtExceptionHandler 17 | { 18 | 19 | @Override 20 | public void uncaughtException(final Thread p1,final Throwable p2) 21 | { 22 | new Thread(){ 23 | public void run(){ 24 | if(p2==null)return; 25 | String msg=p2.getMessage(); 26 | StringBuffer sb=new StringBuffer(); 27 | try 28 | { 29 | sb.append(msg); 30 | sb.append("\n").append(getPackageManager().getPackageInfo(getPackageName(), 0).versionName).append("\n").append(Build.MODEL).append(" ").append(Build.VERSION.RELEASE).append("\n"); 31 | } 32 | catch (PackageManager.NameNotFoundException e) 33 | {} 34 | for (StackTraceElement element:p2.getStackTrace()) 35 | sb.append("\n").append(element.toString()); 36 | Intent intent=new Intent(getApplicationContext(),CrashActivity.class); 37 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 38 | intent.putExtra(Intent.EXTRA_TEXT,sb.toString()); 39 | startActivity(intent); 40 | } 41 | }.start(); 42 | try 43 | { 44 | Thread.sleep(3000); 45 | } 46 | catch (InterruptedException e) 47 | {} 48 | android.os.Process.killProcess(android.os.Process.myPid()); 49 | } 50 | 51 | 52 | @Override 53 | public void onCreate() 54 | { 55 | super.onCreate(); 56 | //Bugly.init(this,"39c93f2bb3",false); 57 | Thread.currentThread().setUncaughtExceptionHandler(this); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/database/MoeData.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.database; 2 | import android.database.sqlite.SQLiteOpenHelper; 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.Cursor; 6 | import android.database.sqlite.SQLiteStatement; 7 | 8 | public class MoeData extends SQLiteOpenHelper 9 | { 10 | public MoeData(Context context){ 11 | super(context,"moe",null,3); 12 | } 13 | 14 | public int update(String key, String value) 15 | { 16 | Cursor c=query(key); 17 | if(c.getCount()==0) 18 | insert(key,value); 19 | else{ 20 | SQLiteDatabase sql=getReadableDatabase(); 21 | SQLiteStatement state=sql.compileStatement("update moe set value=? where key=?"); 22 | state.bindAllArgsAsStrings(new String[]{value,key}); 23 | state.executeUpdateDelete(); 24 | state.close(); 25 | //sql.close(); 26 | } 27 | return 1; 28 | } 29 | 30 | public int delete(String key) 31 | { 32 | SQLiteDatabase sql=getReadableDatabase(); 33 | SQLiteStatement state=sql.compileStatement("delete from moe where key=?"); 34 | state.bindAllArgsAsStrings(new String[]{key}); 35 | state.executeUpdateDelete(); 36 | state.close(); 37 | //sql.close(); 38 | return 1; 39 | } 40 | 41 | public Cursor query(String key) 42 | { 43 | SQLiteDatabase sql=getReadableDatabase(); 44 | synchronized(sql){ 45 | return sql.query("moe",null,"key=?",new String[]{key},null,null,null); 46 | } 47 | } 48 | 49 | public void insert(String key, String value) 50 | { 51 | SQLiteDatabase sql=getReadableDatabase(); 52 | SQLiteStatement state=sql.compileStatement("insert into moe values(?,?)"); 53 | state.bindAllArgsAsStrings(new String[]{key,value}); 54 | state.executeUpdateDelete(); 55 | state.close(); 56 | //sql.close(); 57 | } 58 | 59 | @Override 60 | public void onCreate(SQLiteDatabase p1) 61 | { 62 | p1.execSQL("create table moe(key TEXT primary key,value TEXT)"); 63 | } 64 | 65 | @Override 66 | public void onUpgrade(SQLiteDatabase p1, int p2, int p3) 67 | { 68 | // TODO: Implement this method 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/res/raw/faq: -------------------------------------------------------------------------------- 1 | 3.8.4 2 | 更改柱形图显示效果,支持涟漪动画(网上找的,效果不是很好 3 | 3.8.3 4 | 支持水平或垂直翻转 5 | 3.8.2 6 | 修复设置折线图崩溃bug,优化异常捕捉 7 | 3.8.1 8 | 修复多次预览黑屏bug 9 | 3.8 10 | 优化性能,更流畅的动画效果 11 | 3.7 12 | 新增一个特效 13 | 3.6.2 14 | 新的动画效果 15 | 3.6.1 16 | 完善新频谱的色彩模式 17 | 3.6 18 | 新增一种频谱 19 | 3.5.1 20 | 频谱可倒置 21 | 3.5 22 | 加入后台休眠机制,优化算法,方块频谱可调节高度 23 | 3.4 24 | 特效支持自定义图片 25 | 3.3.9 26 | 新增一种频谱(只支持间隔取色和随机颜色),bug修复 27 | 3.3.8.2 28 | 去除无用类 29 | 3.3.8.1 30 | 修正特效重叠bug,修正气泡颜色 31 | 3.3.8 32 | 气泡特效 33 | 3.3.7.1 34 | bug修复,裁剪图片时抗锯齿 35 | 3.3.7 36 | 更改数据存储方式 37 | 3.3.6.1 38 | 支持设置视频第一帧作为背景 39 | 3.3.5 40 | 新增樱花特效,优化特效算法 41 | 3.3.4 42 | 新增雨滴特效 43 | 3.3.3 44 | 更改主题,可能存在兼容性问题 45 | 3.3.2 46 | 新增屏幕特效(实验性功能) 47 | 3.3.1 48 | 新增打砖块频谱,该频谱不支持圆角 49 | 3.3 50 | 新增方块频谱 51 | 3.2.10 52 | 新增霓虹灯组色彩模式,建议清除数据再使用 53 | 3.2.9 54 | 重构部分代码,折线图使用波形数据绘制 55 | 3.2.8 56 | bug修复 57 | 3.2.7 58 | 进度条支持微调,修复进度显示错误bug 59 | 3.2.6 60 | 可更改色带渐变方向 61 | 3.2.5 62 | 修复横竖屏旋转导致线条间距变大bug 63 | 3.2.4 64 | 可更改霓虹灯变色间隔时长 65 | 3.2.3 66 | 改回对称 67 | 3.2.2 68 | 修复部分横屏bug,重新设计裁剪框生成算法,软件方向不在固定 69 | 3.1.2 70 | 加模式 71 | 3.1.1 72 | bug修复 73 | 3.1 74 | 修复中心圆裁剪bug,又写了一堆,支持横屏模式,本次改动较大,会有不少bug,请及时提交崩溃日志到评论区,点击发送日志会自动复制到剪贴板 75 | 3.0.2 76 | 修复颜色更新bug 77 | 3.0.1 78 | 修复gif动画bug,优化启动速度 79 | 3.0 80 | 自己探索 81 | 2.9.1 82 | 移除bugly,使用360加固 83 | 2.9 84 | 可对中心圆进行一些简单控制 85 | 2.8 86 | 新增两种频谱,原先的图片和颜色失效,需要重新配置 87 | 2.7.1 88 | 修复显示问题,暂时不更了,明天科目一 89 | 2.7 90 | 修复几个bug 91 | 2.6 92 | 中心图支持gif,本次改动较大,可能有明显bug 93 | 2.5 94 | 支持手输十六进制颜色代码,霓虹灯进入过渡动画 95 | 2.4 96 | 新增霓虹灯色彩模式,5s切换一次颜色 97 | 2.3 98 | 支持关闭中心图片旋转(通知栏图块),优化算法,圆形射线频谱不再掉帧 99 | 2.2 100 | 加入高帧率模式,支持调节动画速度 101 | 2.1 102 | 新增一种颜色模式,优化色带算法(圆形射线频谱除外) 103 | 2.0 104 | 加了点简单的动画 105 | 1.9 106 | 提升稳定性 107 | 1.8 108 | 重构部分代码 109 | 1.7 110 | 修复横屏选色遮挡bug,支持设置gif图作背景(不推荐使用),默认30帧刷新,当gif作背景以gif为准(最低30),使用圆环射线频谱会造成严重掉帧,了解一下 111 | 1.6 112 | 修复圆环射线相关bug,新增弹弹圈样式,移除v4,v7等兼容包 113 | 1.5 114 | 新版本需要卸载旧版本再安装 115 | 屏蔽专辑封面相关代码(测试了几款音乐软件,只有酷狗按新版标准开发,但是它不提供专辑封面,其它几款都或多或少有问题,qq音乐在后台,开关其它播放器它就会更新歌曲数据,aplayer在退出后会更新歌曲数据,网易云不会回调数据) 116 | 1.4 117 | 引入bugly,日常写bug 118 | 1.3 119 | 支持折线和圆环射线,优化兼容性 120 | 1.2 121 | 可以将专辑封面作为背景和频谱颜色(支持的播放器较少,网易云音乐支持) 122 | 1.1 123 | 支持设置静态图为背景,可更改频谱的颜色,大小,位置等 124 | 125 | 126 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/line/RadialDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.line; 2 | import android.graphics.Canvas; 3 | import android.content.SharedPreferences; 4 | import com.moe.LiveVisualizer.utils.ColorList; 5 | import com.moe.LiveVisualizer.service.LiveWallpaper; 6 | import android.graphics.Paint; 7 | import android.graphics.Bitmap; 8 | import android.graphics.PorterDuffXfermode; 9 | import android.graphics.PorterDuff; 10 | import android.util.TypedValue; 11 | import android.graphics.LinearGradient; 12 | import android.graphics.Shader; 13 | import com.moe.LiveVisualizer.internal.ImageDraw; 14 | import com.moe.LiveVisualizer.draw.CircleDraw; 15 | import com.moe.LiveVisualizer.draw.LineDraw; 16 | 17 | public class RadialDraw extends LineDraw 18 | { 19 | private float[] points; 20 | public RadialDraw(ImageDraw draw) 21 | { 22 | super(draw); 23 | } 24 | 25 | @Override 26 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) 27 | { 28 | Paint paint=getPaint(); 29 | if ( points == null || points.length != size() ) 30 | points = new float[size()]; 31 | float x=getStartOffset();//起始像素 32 | final float halfWidth=getBorderWidth()/ 2; 33 | for ( int i=0;i < points.length;i ++ ) 34 | { 35 | if(useMode) 36 | checkMode(color_mode,paint); 37 | float height=(float)(buffer[i] / 127d * getBorderHeight()); 38 | if ( height < points[i] ) 39 | points[i]=Math.max(0,points[i]-(points[i]-height)*getInterpolator((points[i]-height)/points[i]*1.6f)); 40 | else if(height>points[i]) 41 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height*0.7f); 42 | if ( paint.getStrokeCap() != Paint.Cap.ROUND ) 43 | { 44 | canvas.drawRect(x, getDrawHeight() - points[i], x + getBorderWidth() , getDrawHeight()+points[i], paint); 45 | x += getSpaceWidth(); 46 | } 47 | else 48 | { 49 | canvas.drawLine(x + halfWidth, getDrawHeight() - points[i], x+halfWidth, getDrawHeight()+points[i], paint); 50 | //canvas.drawLine(x, getDrawHeight() + height + halfWidth, x, getDrawHeight() + halfWidth, paint); 51 | x += getSpaceWidth(); 52 | } 53 | 54 | } 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/line/SquareDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.line; 2 | import com.moe.LiveVisualizer.draw.LineDraw; 3 | import com.moe.LiveVisualizer.internal.ImageDraw; 4 | import com.moe.LiveVisualizer.service.LiveWallpaper; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.RectF; 8 | import android.graphics.PorterDuff; 9 | import android.graphics.PorterDuffXfermode; 10 | import com.moe.LiveVisualizer.utils.ColorList; 11 | 12 | public class SquareDraw extends LineDraw 13 | { 14 | private float[] points; 15 | public SquareDraw(ImageDraw draw){ 16 | super(draw); 17 | } 18 | 19 | private int squareSize(){ 20 | return (int)(getBorderHeight()/getBorderWidth()); 21 | } 22 | @Override 23 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) 24 | { 25 | Paint paint=getPaint(); 26 | if ( points == null || points.length != size() ) 27 | points = new float[size()]; 28 | float x=getStartOffset();//起始像素 29 | final float halfWidth=getBorderWidth()/8; 30 | float itemHeight=(float) Math.floor(getBorderHeight()/20f); 31 | float squareHeight=itemHeight*0.7f; 32 | for ( int i=0;i < points.length;i ++ ) 33 | { 34 | if(useMode) 35 | checkMode(color_mode,paint); 36 | float height=(float)(buffer[i] / (double)Byte.MAX_VALUE * getBorderHeight()); 37 | if ( height < points[i] ) 38 | points[i]=Math.max(0,points[i]-(points[i]-height)*getInterpolator((points[i]-height)/points[i]*1f)*1f); 39 | else if(height>points[i]) 40 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height*0.6f); 41 | float offsetLeft=x; 42 | float offsetRight=x+getBorderWidth(); 43 | x+=getSpaceWidth(); 44 | double size=Math.ceil(points[i]/itemHeight); 45 | for(int n=0;ngetMaxWidth()||getOffsetY()<-getSize()){ 30 | matrix.postTranslate(-getOffsetX(),-getOffsetY()); 31 | setOffsetY(getMaxHeight()); 32 | setOffsetX(getRandom().nextInt(getMaxWidth())-getSize()); 33 | matrix.postTranslate(getOffsetX(),getOffsetY()); 34 | }else if(getOffsetY()height?wind:-wind); 36 | setOffsetX(getOffsetX()+offset); 37 | setOffsetY(getOffsetY()-speed); 38 | matrix.postTranslate(offset,-speed); 39 | canvas.drawBitmap(getEngine().getBuffer(),matrix,paint); 40 | }else{ 41 | setOffsetY(getOffsetY()-speed); 42 | matrix.postTranslate(0,-speed); 43 | } 44 | } 45 | 46 | @Override 47 | public void random(Random random) 48 | { 49 | paint.setColorFilter(new PorterDuffColorFilter(random.nextInt(0x7f7f7f)+0x7f7f7f7f,PorterDuff.Mode.SRC_IN)); 50 | setOffsetX(random.nextInt(getMaxWidth())-getSize()); 51 | if(isFirst()) 52 | setOffsetY(random.nextInt(getMaxHeight())+getMaxHeight()); 53 | else 54 | setOffsetY(getMaxHeight()); 55 | speed=getSize()/getMaxSize()*getSpeed()/5+1; 56 | wind=random.nextFloat()*getWind(); 57 | if(getEngine().getBuffer()!=null) 58 | matrix.setScale(getSize()/getEngine().getBuffer().getWidth(),getSize()/getEngine().getBuffer().getHeight()); 59 | matrix.postTranslate(getOffsetX(),getOffsetY()); 60 | direction=random.nextBoolean(); 61 | height=random.nextInt(getMaxHeight()/2)+getMaxHeight()/4; 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 色带渐变 5 | 间隔取色 6 | 随机颜色 7 | 霓虹灯 8 | 霓虹灯组 9 | 10 | 11 | 柱形图 12 | 折线图 13 | 圆环射线 14 | 弹弹圈 15 | 圆环三角 16 | 射线 17 | 水波纹 18 | 圆环离散点 19 | 山坡线 20 | 方块 21 | 打砖块 22 | 未命名 23 | 未命名2 24 | 未命名3 25 | 心形 26 | 27 | 28 | 0 29 | 1 30 | 2 31 | 3 32 | 4 33 | 34 | 35 | 0 36 | 1 37 | 2 38 | 3 39 | 4 40 | 5 41 | 6 42 | 7 43 | 8 44 | 9 45 | 10 46 | 11 47 | 12 48 | 13 49 | 14 50 | 51 | 52 | 向外 53 | 向内 54 | 55 | 56 | 0 57 | 1 58 | 59 | 60 | 从左至右 61 | 从右至左 62 | 从上至下 63 | 从下至上 64 | 左上至右下 65 | 右上至左下 66 | 左下至右上 67 | 右下至左上 68 | 69 | 70 | 0 71 | 1 72 | 2 73 | 3 74 | 4 75 | 5 76 | 6 77 | 7 78 | 79 | 80 | 雪花 81 | 雨滴 82 | 樱花 83 | 气泡 84 | 图片 85 | 基本图形 86 | 87 | 88 | 0 89 | 1 90 | 2 91 | 3 92 | 4 93 | 5 94 | 95 | 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/duang/Duang.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.duang; 2 | import android.animation.TypeEvaluator; 3 | import android.graphics.Path; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import java.util.Random; 7 | import android.util.DisplayMetrics; 8 | 9 | public abstract class Duang 10 | { 11 | private float offsetX,offsetY,size; 12 | private Random random; 13 | private Engine engine; 14 | private boolean first=true; 15 | public Duang(){ 16 | random=new Random(System.nanoTime()); 17 | } 18 | public Random getRandom(){ 19 | return random; 20 | } 21 | public boolean isFirst(){ 22 | boolean flag=first; 23 | first=false; 24 | return flag; 25 | } 26 | final void setEngine(Engine engine){ 27 | this.engine=engine; 28 | } 29 | public Engine getEngine(){ 30 | return engine; 31 | } 32 | public int getMinSize(){ 33 | return engine.getMinSize(); 34 | } 35 | public int getMaxSize(){ 36 | return engine.getMxSize(); 37 | } 38 | public int getWind() 39 | { 40 | return engine.getWind(); 41 | } 42 | 43 | public int getMaxWidth() 44 | { 45 | return getDisplay().widthPixels; 46 | } 47 | 48 | 49 | public int getMaxHeight() 50 | { 51 | return getDisplay().heightPixels; 52 | } 53 | public DisplayMetrics getDisplay(){ 54 | return engine.getDisplay(); 55 | } 56 | protected void setOffsetX(float offsetX) 57 | { 58 | this.offsetX = offsetX; 59 | } 60 | 61 | public float getOffsetX() 62 | { 63 | return offsetX; 64 | } 65 | 66 | protected void setOffsetY(float offsetY) 67 | { 68 | this.offsetY = offsetY; 69 | } 70 | 71 | public float getOffsetY() 72 | { 73 | return offsetY; 74 | } 75 | 76 | protected void setSize(float size) 77 | { 78 | this.size = size; 79 | } 80 | 81 | public float getSize() 82 | { 83 | return size; 84 | } 85 | 86 | 87 | 88 | public int getSpeed() 89 | { 90 | return engine.getSpeed(); 91 | } 92 | 93 | public abstract void draw(Canvas canvas); 94 | public abstract void random(Random random); 95 | public void reset(boolean random){ 96 | if(random){ 97 | setSize(this.random.nextFloat()*(getMaxSize()-getMinSize())+getMinSize()); 98 | random(this.random); 99 | }else 100 | { 101 | offsetX=0; 102 | offsetY=0; 103 | size=0; 104 | } 105 | } 106 | public void release(){ 107 | reset(false); 108 | engine=null; 109 | try 110 | { 111 | finalize(); 112 | } 113 | catch (Throwable e) 114 | {} 115 | } 116 | 117 | 118 | } 119 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/internal/VideoThread.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.internal; 2 | import android.media.MediaPlayer; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.view.Surface; 5 | import android.graphics.SurfaceTexture; 6 | import android.media.MediaMetadataRetriever; 7 | import java.io.IOException; 8 | import android.graphics.Bitmap; 9 | import java.io.File; 10 | import android.media.MediaCodec; 11 | import android.graphics.BitmapFactory; 12 | import java.util.ArrayList; 13 | import android.media.MediaDataSource; 14 | import java.io.InputStream; 15 | import java.io.FileDescriptor; 16 | import java.util.Iterator; 17 | import android.graphics.Canvas; 18 | import android.graphics.Rect; 19 | import android.view.SurfaceHolder; 20 | import android.view.SurfaceHolder.Callback; 21 | import android.graphics.SurfaceTexture.OnFrameAvailableListener; 22 | import android.os.Handler; 23 | import android.view.TextureView; 24 | import java.lang.reflect.Constructor; 25 | import java.lang.reflect.InvocationTargetException; 26 | import java.lang.reflect.Proxy; 27 | import java.lang.reflect.InvocationHandler; 28 | import java.lang.reflect.Method; 29 | import java.lang.reflect.Field; 30 | 31 | public class VideoThread extends Thread 32 | { 33 | private MediaMetadataRetriever meta; 34 | private String path; 35 | private long duration,current,oldTime; 36 | private boolean playing; 37 | private ArrayList list=new ArrayList<>(); 38 | public VideoThread(String path){ 39 | this.path=path; 40 | meta=new MediaMetadataRetriever(); 41 | } 42 | 43 | public void notifyVisiableChanged(boolean visible) 44 | { 45 | playing=visible; 46 | if(playing) 47 | oldTime=System.currentTimeMillis(); 48 | } 49 | 50 | public void onSizeChanged() 51 | { 52 | // TODO: Implement this method 53 | } 54 | @Override 55 | public void run() 56 | { 57 | meta.setDataSource(path); 58 | duration=Long.parseLong(meta.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)); 59 | try{ 60 | for(long i=0;i=list.size()) 72 | current=0; 73 | Bitmap b=list.get((int)current); 74 | current++; 75 | return b; 76 | }catch(Exception e){} 77 | return null; 78 | } 79 | public void destroy(){ 80 | meta.release(); 81 | Iterator iterator=list.iterator(); 82 | while(iterator.hasNext()){ 83 | iterator.next().recycle(); 84 | iterator.remove(); 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/circle/CircleDisperseDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.circle; 2 | import com.moe.LiveVisualizer.internal.ImageDraw; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.SweepGradient; 7 | import android.graphics.Bitmap; 8 | import android.graphics.PorterDuffXfermode; 9 | import android.graphics.PorterDuff; 10 | import android.graphics.Shader; 11 | import android.graphics.PointF; 12 | import android.graphics.LinearGradient; 13 | import com.moe.LiveVisualizer.utils.ColorList; 14 | 15 | public class CircleDisperseDraw extends RingDraw 16 | { 17 | private float[] points; 18 | 19 | public CircleDisperseDraw(ImageDraw draw) 20 | { 21 | super(draw); 22 | } 23 | 24 | @Override 25 | public void onDraw(Canvas canvas, int color_mode) 26 | { 27 | super.onDraw(canvas,color_mode); 28 | drawCircleImage(canvas); 29 | 30 | } 31 | 32 | @Override 33 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) 34 | { 35 | PointF point=getPointF(); 36 | float radius=getRadius(); 37 | final float radialHeight=getDirection()==OUTSIDE?getBorderHeight():getRadius(); 38 | Paint paint=getPaint(); 39 | paint.setStrokeWidth(getBorderWidth()); 40 | if ( points == null || points.length != size() ) 41 | points = new float[size()]; 42 | float degress_step=360f / size(); 43 | canvas.save(); 44 | //final PointF center=getPointF(); 45 | canvas.rotate(degress_step / 2f, point.x, point.y); 46 | for ( int i=0;i < points.length;i ++ ) 47 | { 48 | if(useMode) 49 | checkMode(color_mode,paint); 50 | float height=(float) (buffer[i] / 127d * radialHeight); 51 | if ( height < points[i] ) 52 | points[i]=Math.max(0,points[i]-(points[i]-height)*getInterpolator((points[i]-height)/points[i]*0.8f)*0.45f); 53 | else if(height>points[i]) 54 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height); 55 | height=points[i]; 56 | if(paint.getStrokeCap()==Paint.Cap.ROUND) 57 | canvas.drawLine(point.x,point.y-radius+(getDirection()==OUTSIDE?- height:height), point.x, point.y -radius+(getDirection()==OUTSIDE?- height:height), paint); 58 | else 59 | canvas.drawRect(point.x-getBorderWidth()/2, point.y -radius+(getDirection()==OUTSIDE?- height:height), point.x + getBorderWidth()/2, point.y -radius+(getDirection()==OUTSIDE?- height-getBorderWidth():height+getBorderWidth()), paint); 60 | canvas.rotate(degress_step, point.x, point.y); 61 | //degress+=degress_step; 62 | } 63 | canvas.restore(); 64 | } 65 | 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/CircleDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw; 2 | import com.moe.LiveVisualizer.internal.ImageDraw; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.PointF; 7 | import android.graphics.Bitmap; 8 | import android.graphics.PorterDuffXfermode; 9 | import android.graphics.PorterDuff; 10 | import android.graphics.Matrix; 11 | 12 | public abstract class CircleDraw extends Draw 13 | { 14 | private PointF point; 15 | private boolean rotation; 16 | private int num; 17 | public CircleDraw(ImageDraw draw){ 18 | super(draw); 19 | LiveWallpaper.WallpaperEngine engine=draw.getEngine(); 20 | point=new PointF(); 21 | point.x=engine.getPreference().getInt("offsetX",Math.min(engine.getDisplayWidth(),engine.getDisplayHeight())/2); 22 | point.y=engine.getPreference().getInt("offsetY",Math.max(engine.getDisplayHeight(),engine.getDisplayWidth())/2); 23 | num=engine.getPreference().getInt("num",50); 24 | if(engine.getDisplayWidth()>engine.getDisplayHeight()){ 25 | float x=point.x; 26 | point.x=point.y; 27 | point.y=x; 28 | } 29 | } 30 | 31 | public void setVisualizerRotation(boolean rotation) 32 | { 33 | this.rotation=rotation; 34 | } 35 | 36 | @Override 37 | public void notifySizeChanged() 38 | { 39 | point.x=getEngine().getPreference().getInt("offsetX",Math.min(getEngine().getDisplayWidth(),getEngine().getDisplayHeight())/2); 40 | point.y=getEngine().getPreference().getInt("offsetY",Math.max(getEngine().getDisplayHeight(),getEngine().getDisplayWidth())/2); 41 | if(getEngine().getDisplayWidth()>getEngine().getDisplayHeight()){ 42 | float x=point.x; 43 | point.x=point.y; 44 | point.y=x; 45 | } 46 | } 47 | public boolean isVisualizerRotation(){ 48 | return rotation; 49 | } 50 | 51 | @Override 52 | public void setNum(int num) { 53 | this.num=num; 54 | } 55 | 56 | public int getSize(){ 57 | return num; 58 | } 59 | @Override 60 | public void setOffsetX(int x) 61 | { 62 | if(getEngine().getDisplayWidth()>getEngine().getDisplayHeight()) 63 | point.y=x; 64 | else 65 | point.x=x; 66 | } 67 | 68 | @Override 69 | public void setOffsetY(int y) 70 | { 71 | if(getEngine().getDisplayWidth()>getEngine().getDisplayHeight()) 72 | point.x=y; 73 | else 74 | point.y=y; 75 | } 76 | 77 | 78 | @Override 79 | final public void onDrawHeightChanged(float height) 80 | { 81 | // TODO: Implement this method 82 | } 83 | 84 | public PointF getPointF(){ 85 | return point; 86 | } 87 | 88 | @Override 89 | public void finalized() 90 | { 91 | // TODO: Implement this method 92 | super.finalized(); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/circle/UnKnow3.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.circle; 2 | import com.moe.LiveVisualizer.internal.ImageDraw; 3 | import android.graphics.Canvas; 4 | import com.moe.LiveVisualizer.service.LiveWallpaper; 5 | import com.moe.LiveVisualizer.utils.ColorList; 6 | import android.graphics.PointF; 7 | import android.graphics.Paint; 8 | import android.graphics.RectF; 9 | import android.graphics.Path; 10 | 11 | public class UnKnow3 extends RingDraw 12 | { 13 | private float[] points; 14 | private float width; 15 | private Path lines=new Path(); 16 | public UnKnow3(ImageDraw draw){ 17 | super(draw); 18 | } 19 | @Override 20 | public void onSizeChanged() 21 | { 22 | // TODO: Implement this method 23 | super.onSizeChanged(); 24 | width=(float)(2*getRadius()*Math.PI/(size()-1)); 25 | 26 | } 27 | 28 | @Override 29 | public void onDraw(Canvas canvas, int color_mode) 30 | { 31 | drawCircleImage(canvas); 32 | super.onDraw(canvas, color_mode); 33 | } 34 | 35 | @Override 36 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) 37 | { 38 | PointF center=getPointF(); 39 | Paint paint=getPaint(); 40 | paint.setAntiAlias(true); 41 | paint.setStyle(Paint.Style.STROKE); 42 | paint.setStrokeWidth(getBorderWidth()); 43 | paint.setStrokeCap(getRound()); 44 | if(points==null||points.length!=size()) 45 | points=new float[size()]; 46 | canvas.save(); 47 | canvas.rotate(-90,center.x,center.y); 48 | canvas.translate(center.x,center.y); 49 | double degress=2d/size()*Math.PI; 50 | /*float halfWidth=width/2;*/ 51 | float halfBorder=getBorderWidth()/2f; 52 | float radius=getRadius(); 53 | for(int i=0;ipoints[i]) 58 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height); 59 | height=points[i]; 60 | if(useMode) 61 | checkMode(color_mode,paint); 62 | double value=degress*i; 63 | lines.moveTo((float)((radius-points[i])*Math.cos(value)),(float)((radius-points[i])*Math.sin(value))); 64 | lines.lineTo((float)((radius+points[i])*Math.cos(value)),(float)((radius+points[i])*Math.sin(value))); 65 | value=degress*(i+1); 66 | lines.lineTo((float)((radius+points[i])*Math.cos(value)),(float)((radius+points[i])*Math.sin(value))); 67 | lines.lineTo((float)((radius-points[i])*Math.cos(value)),(float)((radius-points[i])*Math.sin(value))); 68 | lines.close(); 69 | if(useMode){ 70 | canvas.drawPath(lines,paint); 71 | lines.reset(); 72 | } 73 | } 74 | if(!useMode) 75 | canvas.drawPath(lines,paint); 76 | lines.reset(); 77 | canvas.restore(); 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/line/YamaLineDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.line; 2 | import android.graphics.*; 3 | 4 | import android.util.TypedValue; 5 | import com.moe.LiveVisualizer.service.LiveWallpaper; 6 | import com.moe.LiveVisualizer.draw.LineDraw; 7 | import com.moe.LiveVisualizer.internal.ImageDraw; 8 | import com.moe.LiveVisualizer.utils.ColorList; 9 | 10 | public class YamaLineDraw extends LineDraw 11 | { 12 | private float[] points; 13 | public YamaLineDraw(ImageDraw draw) 14 | { 15 | super(draw); 16 | } 17 | 18 | /*@Override 19 | public void onDraw(Canvas canvas, int color_mode) 20 | { 21 | Paint paint=getPaint(); 22 | switch(color_mode){ 23 | case 0: 24 | switch ( getEngine().getColorList().size() ) 25 | { 26 | case 0: 27 | paint.setColor(0xff39c5bb); 28 | drawGraph(getFft(), canvas, color_mode, false); 29 | break; 30 | case 1: 31 | paint.setColor(getEngine().getColorList().get(0)); 32 | drawGraph(getFft(), canvas, color_mode, false); 33 | break; 34 | default: 35 | paint.setShader(getShader()); 36 | drawGraph(getFft(), canvas, color_mode, false); 37 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 38 | paint.setShader(null); 39 | break; 40 | } 41 | break; 42 | case 1: 43 | case 4: 44 | case 2: 45 | drawGraph(getFft(), canvas, color_mode, true); 46 | break; 47 | case 3: 48 | int color=getColor(); 49 | paint.setColor(getEngine().getPreference().getBoolean("nenosync",false)?color:0xffffffff); 50 | paint.setShadowLayer(paint.getStrokeWidth(),0,0,color); 51 | drawGraph(getFft(), canvas, color_mode, false); 52 | paint.setShadowLayer(0, 0, 0, 0); 53 | break; 54 | } 55 | paint.reset(); 56 | 57 | }*/ 58 | @Override 59 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) 60 | { 61 | Paint paint=getPaint(); 62 | if ( points == null || points.length != size() ) 63 | points = new float[size()]; 64 | final float halfWidth=getBorderWidth() / 2; 65 | float x=getStartOffset(); 66 | for ( int i=0;i < points.length;i ++ ) 67 | { 68 | if(useMode) 69 | checkMode(color_mode,paint); 70 | float height=(float)(buffer[i] / 127d * getBorderHeight()); 71 | if ( height < points[i] ) 72 | points[i]=Math.max(0,points[i]-(points[i]-height)*getInterpolator((points[i]-height)/points[i]*0.8f)*0.45f); 73 | else if(height>points[i]) 74 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height); 75 | height=points[i]; 76 | canvas.drawLine(halfWidth, getDrawHeight(), x+=halfWidth, getDrawHeight()-height, paint); 77 | canvas.drawLine(x, getDrawHeight() - height, canvas.getWidth()-halfWidth, getDrawHeight(), paint); 78 | x += halfWidth + getSpaceWidth(); 79 | 80 | 81 | } 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/utils/PreferencesUtils.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.utils; 2 | import android.content.Context; 3 | import android.net.Uri; 4 | import android.database.Cursor; 5 | import java.util.Set; 6 | import java.util.Map; 7 | import java.util.HashMap; 8 | import com.moe.LiveVisualizer.service.SharedPreferences; 9 | import android.os.Handler; 10 | import android.content.ContentResolver; 11 | import android.database.ContentObserver; 12 | 13 | public class PreferencesUtils 14 | { 15 | private ContentObserver observer; 16 | private Context context; 17 | private Map buffer; 18 | public PreferencesUtils(Context context){ 19 | this.context=context; 20 | context.getContentResolver().registerContentObserver(Uri.parse(SharedPreferences.URI),true,observer=new ContentObserver(new Handler()){ 21 | public void onChange(boolean p1,Uri p2){ 22 | buffer.put(p2.getQueryParameter("key"),getString(null,p2)); 23 | } 24 | }); 25 | buffer=new HashMap<>(); 26 | } 27 | public synchronized String getString(String key,String defaultVlue){ 28 | String value=buffer.get(key); 29 | if(value!=null)return value; 30 | Cursor cursor=context.getContentResolver().query(getUriBuilder().appendQueryParameter("key",key).build(),null,null,null,null,null); 31 | if(cursor!=null){ 32 | if(cursor.moveToFirst()) 33 | value=cursor.getString(1); 34 | cursor.close(); 35 | } 36 | if(value==null) 37 | value=defaultVlue; 38 | buffer.put(key,value); 39 | return value; 40 | } 41 | public int getInt(String key,int defaultValue){ 42 | return Integer.parseInt(getString(key,defaultValue+"")); 43 | } 44 | public boolean getBoolean(String key,boolean defaultVlue){ 45 | return Boolean.parseBoolean(getString(key,defaultVlue+"")); 46 | } 47 | public static String getString(Context context,Uri uri){ 48 | if(context!=null){ 49 | String value=null; 50 | Cursor cursor=context.getContentResolver().query(uri,null,null,null,null,null); 51 | if(cursor!=null){ 52 | if(cursor.moveToFirst()) 53 | value=cursor.getString(1); 54 | cursor.close(); 55 | } 56 | return value; 57 | } 58 | return uri.getQueryParameter("value"); 59 | } 60 | public static int getInt(Context context,Uri uri,int defaultValue){ 61 | String value=getString(context,uri); 62 | if(value==null) 63 | return defaultValue; 64 | else 65 | return Integer.parseInt(value); 66 | } 67 | public static boolean getBoolean(Context context,Uri uri,boolean defaultValue){ 68 | String value=getString(context,uri); 69 | if(value==null) 70 | return defaultValue; 71 | else 72 | return Boolean.parseBoolean(value); 73 | } 74 | public static Uri.Builder getUriBuilder(){ 75 | return new Uri.Builder().scheme("content").authority("moe").path("moe"); 76 | } 77 | public void close(){ 78 | if(observer!=null) 79 | context.getContentResolver().unregisterContentObserver(observer); 80 | context=null; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/circle/UnKnow1.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.circle; 2 | import com.moe.LiveVisualizer.internal.ImageDraw; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.graphics.Canvas; 5 | import android.graphics.Path; 6 | import android.graphics.PointF; 7 | import android.graphics.Paint; 8 | import java.util.Random; 9 | import com.moe.LiveVisualizer.utils.ColorList; 10 | 11 | public class UnKnow1 extends RingDraw { 12 | private float[] points; 13 | public UnKnow1(ImageDraw draw) { 14 | super(draw); 15 | } 16 | @Override 17 | public void onDraw(Canvas canvas, int color_mode) { 18 | super.onDraw(canvas, color_mode); 19 | drawCircleImage(canvas); 20 | } 21 | 22 | @Override 23 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) { 24 | PointF center=getPointF(); 25 | Paint paint=getPaint(); 26 | if (points == null) 27 | points = new float[20]; 28 | canvas.save(); 29 | int count=-1; 30 | for (int i=0;i < 5;i++) { 31 | if (useMode) 32 | checkMode(color_mode, paint); 33 | //计算高度 34 | for (int n=0;n < 4;n++) { 35 | float height=(float)buffer[++count]; 36 | if ( height < points[count] ) 37 | points[count]=Math.max(0,points[count]-(points[count]-height)*getInterpolator((points[count]-height)/points[count])*0.8f); 38 | else if(height>points[i]) 39 | points[count]=points[count]+(height-points[count])*getInterpolator((height-points[count])/height); 40 | } 41 | canvas.rotate(i * 15, center.x, center.y); 42 | Path path=new Path(); 43 | path.moveTo(center.x, center.y - getRadius() - Math.abs((points[i * 4 + 3] - points[i * 4]) / 2)); 44 | path.cubicTo(center.x + getRadius() / 2 + points[i * 4], center.y - getRadius() - points[i * 4], center.x + getRadius() + points[i * 4], center.y - getRadius() / 2 - points[i * 4], center.x + getRadius() + Math.abs((points[i * 4] - points[i * 4 + 1]) / 2), center.y); 45 | path.cubicTo(center.x + getRadius() + points[i * 4 + 1], center.y + getRadius() / 2 + points[i * 4 + 1], center.x + getRadius() / 2 + points[i * 4 + 1], center.y + getRadius() + points[i * 4 + 1], center.x, center.y + getRadius() + Math.abs((points[i * 4 + 1] - points[i * 4 + 2]) / 2)); 46 | path.cubicTo(center.x - getRadius() / 2 - points[i * 4 + 2], center.y + getRadius() + points[i * 4 + 2], center.x - getRadius() - points[i * 4 + 2], center.y + getRadius() / 2 + points[i * 4 + 2], center.x - getRadius() - Math.abs((points[i * 4 + 2] - points[i * 4 + 3]) / 2), center.y); 47 | path.cubicTo(center.x - getRadius() - points[i * 4 + 3], center.y - getRadius() / 2 - points[i * 4 + 3], center.x - getRadius() / 2 - points[i * 4 + 3], center.y - getRadius() - points[i * 4 + 3], center.x, center.y - getRadius() - Math.abs((points[i * 4 + 3] - points[i * 4]) / 2)); 48 | path.addCircle(center.x, center.y, getRadius(), Path.Direction.CCW); 49 | path.close(); 50 | canvas.drawPath(path, paint); 51 | 52 | } 53 | canvas.restore(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/line/PopCircleDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.line; 2 | import com.moe.LiveVisualizer.service.LiveWallpaper; 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.util.TypedValue; 6 | import android.graphics.Bitmap; 7 | import android.graphics.PorterDuffXfermode; 8 | import android.graphics.PorterDuff; 9 | import android.graphics.LinearGradient; 10 | import android.view.SurfaceHolder; 11 | import android.graphics.Shader; 12 | import com.moe.LiveVisualizer.internal.ImageDraw; 13 | import com.moe.LiveVisualizer.draw.LineDraw; 14 | import com.moe.LiveVisualizer.utils.ColorList; 15 | 16 | public class PopCircleDraw extends LineDraw 17 | { 18 | private float[] points; 19 | public PopCircleDraw(ImageDraw draw){ 20 | super(draw); 21 | } 22 | 23 | /*@Override 24 | public void onDraw(Canvas canvas, int color_mode) 25 | { 26 | Paint paint=getPaint(); 27 | switch(color_mode){ 28 | case 0: 29 | switch(getEngine().getColorList().size()){ 30 | case 0: 31 | paint.setColor(0xff39c5bb); 32 | drawGraph(getFft(),canvas,color_mode,false); 33 | break; 34 | case 1: 35 | paint.setColor(getEngine().getColorList().get(0)); 36 | drawGraph(getFft(),canvas,color_mode,false); 37 | break; 38 | default: 39 | 40 | paint.setShader(getShader()); 41 | drawGraph(getFft(),canvas,color_mode,false); 42 | paint.setShader(null); 43 | break; 44 | } 45 | break; 46 | case 1: 47 | case 4: 48 | case 2: 49 | drawGraph(getFft(),canvas,color_mode,true); 50 | break; 51 | case 3: 52 | int color=getColor(); 53 | paint.setColor(getEngine().getPreference().getBoolean("nenosync",false)?color:0xffffffff); 54 | paint.setShadowLayer(paint.getStrokeWidth(),0,0,color); 55 | drawGraph(getFft(),canvas,color_mode,false); 56 | paint.setShadowLayer(0,0,0,0); 57 | break; 58 | } 59 | paint.reset(); 60 | 61 | } 62 | */ 63 | @Override 64 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) 65 | { 66 | Paint paint=getPaint(); 67 | paint.setStrokeWidth(2); 68 | paint.setStyle(Paint.Style.STROKE); 69 | if(points==null||points.length!=size()) 70 | points=new float[size()]; 71 | float radius=getBorderWidth()/2.0f; 72 | float x=radius;//起始像素 73 | float y=getDrawHeight(); 74 | //float y=canvas.getHeight() - engine.getPreference().getInt("height", 10) / 100.0f * canvas.getHeight(); 75 | for ( int i=0;i < points.length;i ++ ) 76 | { 77 | if(useMode) 78 | checkMode(color_mode,paint); 79 | float height=(float)(buffer[i]/127d*getBorderHeight()); 80 | if ( height < points[i] ) 81 | points[i]=Math.max(0,points[i]-(points[i]-height)*getInterpolator((points[i]-height)/points[i]*1f)*1f); 82 | else if(height>points[i]) 83 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height*0.6f); 84 | height=points[i]; 85 | canvas.drawCircle(x,y-height-radius,radius,paint); 86 | x+=getSpaceWidth(); 87 | } 88 | } 89 | 90 | 91 | 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/duang/Graph.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.duang; 2 | import android.util.DisplayMetrics; 3 | import android.graphics.Canvas; 4 | import java.util.Random; 5 | import android.graphics.Paint; 6 | import android.graphics.Path; 7 | import android.graphics.Matrix; 8 | 9 | public class Graph extends Duang 10 | { 11 | private float rotate,offsetX,offsetY; 12 | private int alpha; 13 | private Paint paint=new Paint(); 14 | private Path path=new Path(); 15 | private boolean direction; 16 | private Matrix matrix=new Matrix(); 17 | private boolean repeat; 18 | public Graph(){ 19 | paint.setStrokeWidth(2); 20 | } 21 | @Override 22 | public void draw(Canvas canvas) 23 | { 24 | alpha+=repeat?-4:3; 25 | if(alpha<0||getOffsetX()<-getSize()||getOffsetX()>getMaxWidth()+getSize()||getOffsetY()<-getSize()||getOffsetY()>getMaxHeight()+getSize()){ 26 | reset(true); 27 | } 28 | if(alpha>0x8f){ 29 | repeat=true; 30 | alpha=0x8f; 31 | } 32 | paint.setAlpha(alpha); 33 | scrollBy(offsetX,offsetY); 34 | path.offset(offsetX,offsetY); 35 | matrix.setRotate(direction?rotate:-rotate,getOffsetX(),getOffsetY()); 36 | path.transform(matrix); 37 | //paint.setStyle(Paint.Style.FILL); 38 | canvas.drawPath(path,paint); 39 | //paint.setStyle(Paint.Style.STROKE); 40 | //paint.setShadowLayer(2,0,0,paint.getColor()|0xff000000); 41 | //canvas.drawPath(path,paint); 42 | //paint.setShadowLayer(0,0,0,0); 43 | } 44 | 45 | @Override 46 | public void random(Random random) 47 | { 48 | alpha=0; 49 | repeat=false; 50 | //生成左标 51 | setOffsetX(random.nextInt(getMaxWidth()/3)+getMaxWidth()/3); 52 | setOffsetY(random.nextInt(getMaxWidth()/3)+(getMaxHeight()-getMaxWidth()/3)/2); 53 | //生成图形 54 | path.reset(); 55 | switch(GRAPH.$VALUES[random.nextInt(3)]){ 56 | case SQUARE: 57 | path.addRect(getOffsetX()-getSize(),getOffsetY()-getSize(),getOffsetX()+getSize(),getOffsetY()+getSize(),Path.Direction.CW); 58 | break; 59 | case TRIANGLE: 60 | double degress=2d/3*Math.PI; 61 | path.moveTo(getOffsetX()+(float)(getSize()*Math.cos(0)),getOffsetY()+(float)(getSize()*Math.sin(0))); 62 | path.lineTo(getOffsetX()+(float)(getSize()*Math.cos(degress)),getOffsetY()+(float)(getSize()*Math.sin(degress))); 63 | path.lineTo(getOffsetX()+(float)(getSize()*Math.cos(degress*2)),getOffsetY()+(float)(getSize()*Math.sin(2*degress))); 64 | path.close(); 65 | break; 66 | case ROUND: 67 | path.addCircle(getOffsetX(),getOffsetY(),getSize(),Path.Direction.CW); 68 | break; 69 | } 70 | //随机颜色 71 | paint.setColor(random.nextInt(0xffffff)|0x5f000000); 72 | // 73 | offsetX=(random.nextFloat()*getWind()+1f)*(random.nextBoolean()?2.5f:-2.5f); 74 | offsetY=(random.nextFloat()*getSpeed()+0.01f)*(random.nextBoolean()?0.25f:-0.25f); 75 | direction=random.nextBoolean(); 76 | rotate=random.nextFloat()+1f; 77 | //matrix.reset(); 78 | //matrix.setTranslate(getOffsetX(),getOffsetY()); 79 | } 80 | 81 | enum GRAPH{ 82 | SQUARE,ROUND,TRIANGLE; 83 | } 84 | 85 | @Override 86 | public float getSize() 87 | { 88 | return super.getSize()/2; 89 | } 90 | private void scrollBy(float x,float y){ 91 | setOffsetX(getOffsetX()+x); 92 | setOffsetY(getOffsetY()+y); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/circle/CircleRadialDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.circle; 2 | import android.graphics.Paint; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.graphics.Canvas; 5 | import android.graphics.Bitmap; 6 | import android.graphics.PorterDuffXfermode; 7 | import android.graphics.PorterDuff; 8 | import android.util.TypedValue; 9 | import android.graphics.LinearGradient; 10 | import android.graphics.Shader; 11 | import android.graphics.RadialGradient; 12 | import android.graphics.SweepGradient; 13 | import android.graphics.Point; 14 | import android.graphics.PointF; 15 | import com.moe.LiveVisualizer.internal.ImageDraw; 16 | import com.moe.LiveVisualizer.internal.OnColorSizeChangedListener; 17 | import android.graphics.RectF; 18 | import android.content.SharedPreferences; 19 | import com.moe.LiveVisualizer.utils.ColorList; 20 | 21 | public class CircleRadialDraw extends RingDraw 22 | { 23 | private float[] points; 24 | public CircleRadialDraw(ImageDraw draw) 25 | { 26 | super(draw); 27 | } 28 | 29 | @Override 30 | public void onDraw(Canvas canvas, int color_mode) 31 | { 32 | super.onDraw(canvas,color_mode); 33 | drawCircleImage(canvas); 34 | 35 | } 36 | 37 | @Override 38 | public int size() 39 | { 40 | return super.size()/2; 41 | } 42 | 43 | @Override 44 | public void drawGraph(double[] buffer, Canvas canvas, final int color_mode,boolean useMode) 45 | { 46 | PointF point=getPointF(); 47 | float radius=getRadius(); 48 | final float radialHeight=getDirection()==OUTSIDE?getBorderHeight():getRadius(); 49 | Paint paint=getPaint(); 50 | paint.setStrokeWidth(getBorderWidth()); 51 | if ( points == null || points.length != size() ) 52 | points = new float[size()]; 53 | float degress_step=180f / size(); 54 | canvas.save(); 55 | final PointF center=getPointF(); 56 | canvas.rotate(degress_step / 2.0f, center.x, center.y); 57 | int end=size() - 1; 58 | for ( int i=0;i < points.length;i ++ ) 59 | { 60 | if(useMode) 61 | checkMode(color_mode,paint); 62 | float height=(float) (buffer[i] / 127d * radialHeight); 63 | if ( height < points[i] ) 64 | points[i]=Math.max(0,points[i]-(points[i]-height)*getInterpolator((points[i]-height)/points[i])*0.8f); 65 | else if(height>points[i]) 66 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height); 67 | height=points[i]; 68 | if(paint.getStrokeCap()==Paint.Cap.ROUND) 69 | canvas.drawLine(point.x,point.y-radius, point.x, point.y -radius+(getDirection()==OUTSIDE?- height:height), paint); 70 | else 71 | canvas.drawRect(point.x-getBorderWidth()/2, point.y-radius, point.x + getBorderWidth()/2, point.y -radius+(getDirection()==OUTSIDE?- height:height), paint); 72 | canvas.rotate(degress_step, center.x, center.y); 73 | //degress+=degress_step; 74 | if ( i == end ) 75 | { 76 | if ( degress_step > 0 ) 77 | { 78 | canvas.restore(); 79 | canvas.save(); 80 | degress_step = -degress_step; 81 | canvas.rotate(degress_step / 2.0f, center.x, center.y); 82 | i = -1; 83 | } 84 | else 85 | { 86 | break; 87 | } 88 | } 89 | } 90 | canvas.restore(); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/res/layout/seekbar_preference.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 22 | 23 | 29 | 30 | 39 | 40 | 49 | 50 | 51 | 52 | 59 | 60 | 61 | 62 | 69 | 70 | 78 | 79 | 88 | 89 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/circle/UnKnow2.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.circle; 2 | import com.moe.LiveVisualizer.internal.ImageDraw; 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.graphics.PointF; 6 | import android.graphics.Path; 7 | import android.graphics.RectF; 8 | import android.graphics.SweepGradient; 9 | import android.graphics.PorterDuffXfermode; 10 | import android.graphics.Bitmap; 11 | import android.graphics.PorterDuff; 12 | import com.moe.LiveVisualizer.service.LiveWallpaper; 13 | import com.moe.LiveVisualizer.utils.ColorList; 14 | 15 | public class UnKnow2 extends RingDraw 16 | { 17 | private float[] points; 18 | private float width; 19 | private float[] lines=new float[4]; 20 | private Path path1=new Path(),path2=new Path(); 21 | 22 | public UnKnow2(ImageDraw draw){ 23 | super(draw); 24 | } 25 | @Override 26 | public void onSizeChanged() 27 | { 28 | // TODO: Implement this method 29 | super.onSizeChanged(); 30 | width=(float)(2*getRadius()*Math.PI/(size()-1)); 31 | 32 | } 33 | 34 | @Override 35 | public void onDraw(Canvas canvas, int color_mode) 36 | { 37 | drawCircleImage(canvas); 38 | super.onDraw(canvas, color_mode); 39 | } 40 | 41 | @Override 42 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) 43 | { 44 | PointF center=getPointF(); 45 | Paint paint=getPaint(); 46 | paint.setAntiAlias(true); 47 | paint.setStyle(Paint.Style.STROKE); 48 | paint.setStrokeWidth(getBorderWidth()); 49 | paint.setStrokeCap(getRound()); 50 | if(points==null||points.length!=size()) 51 | points=new float[size()]; 52 | canvas.save(); 53 | canvas.rotate(-90,center.x,center.y); 54 | canvas.translate(center.x,center.y); 55 | double degress=2d/size()*Math.PI; 56 | /*float halfWidth=width/2; 57 | float halfBorder=getBorderWidth()/2f;*/ 58 | float radius=getRadius(); 59 | for(int i=0;ipoints[i]) 64 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height*0.6f); 65 | height=points[i]; 66 | double value=degress*i; 67 | if (i==0){ 68 | path1.moveTo(lines[0]=(float)((radius-points[i])*Math.cos(value)),lines[1]=(float)((radius-points[i])*Math.sin(value))); 69 | path2.moveTo(lines[2]=(float)((radius+points[i])*Math.cos(value)),lines[3]=(float)((radius+points[i])*Math.sin(value))); 70 | 71 | }else{ 72 | path1.lineTo(lines[0]=(float)((radius-points[i])*Math.cos(value)),lines[1]=(float)((radius-points[i])*Math.sin(value))); 73 | path2.lineTo(lines[2]=(float)((radius+points[i])*Math.cos(value)),lines[3]=(float)((radius+points[i])*Math.sin(value))); 74 | } 75 | if(useMode) 76 | checkMode(color_mode,paint); 77 | canvas.drawLines(lines,paint); 78 | //canvas.rotate(degress,center.x,center.y); 79 | } 80 | path1.close(); 81 | path2.close(); 82 | canvas.drawPath(path1,paint); 83 | canvas.drawPath(path2,paint); 84 | path1.reset(); 85 | path2.reset(); 86 | canvas.restore(); 87 | 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/res/layout/seekbar_preference_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 22 | 23 | 29 | 30 | 39 | 40 | 49 | 50 | 51 | 52 | 59 | 60 | 61 | 62 | 69 | 70 | 78 | 79 | 88 | 89 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/circle/HeartDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.circle; 2 | import android.graphics.Canvas; 3 | import com.moe.LiveVisualizer.internal.ImageDraw; 4 | import android.graphics.Path; 5 | import android.graphics.PointF; 6 | import java.util.List; 7 | import java.util.ArrayList; 8 | import android.graphics.Paint; 9 | 10 | public class HeartDraw extends RingDraw 11 | { 12 | private List mPointDatas; 13 | private List mPointControlls; 14 | 15 | public HeartDraw(ImageDraw draw){ 16 | super(draw); 17 | } 18 | @Override 19 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) throws NullPointerException 20 | { 21 | if(mPointControlls==null){ 22 | mPointDatas = new ArrayList<>(); 23 | mPointControlls = new ArrayList<>(); 24 | }else{ 25 | mPointDatas.clear(); 26 | mPointControlls.clear(); 27 | } 28 | PointF center=getPointF(); 29 | 30 | float mCenterX = center.x; 31 | float mCenterY = center.y; 32 | float mCircleRadius=getRadius(); 33 | 34 | 35 | //初始化数据点数据和辅助点位置 36 | mPointDatas.add(new PointF(mCenterX, mCenterY - mCircleRadius)); 37 | mPointDatas.add(new PointF(mCenterX + mCircleRadius, mCenterY)); 38 | mPointDatas.add(new PointF(mCenterX, mCenterY + mCircleRadius)); 39 | mPointDatas.add(new PointF(mCenterX - mCircleRadius, mCenterY)); 40 | 41 | mPointControlls.add(new PointF(mCenterX + mCircleRadius / 2, mCenterY - mCircleRadius)); 42 | mPointControlls.add(new PointF(mCenterX + mCircleRadius, mCenterY - mCircleRadius / 2)); 43 | 44 | mPointControlls.add(new PointF(mCenterX + mCircleRadius, mCenterY + mCircleRadius / 2)); 45 | mPointControlls.add(new PointF(mCenterX + mCircleRadius / 2, mCenterY + mCircleRadius)); 46 | 47 | mPointControlls.add(new PointF(mCenterX - mCircleRadius / 2, mCenterY + mCircleRadius)); 48 | mPointControlls.add(new PointF(mCenterX - mCircleRadius, mCenterY + mCircleRadius / 2)); 49 | 50 | mPointControlls.add(new PointF(mCenterX - mCircleRadius, mCenterY - mCircleRadius / 2)); 51 | mPointControlls.add(new PointF(mCenterX - mCircleRadius / 2, mCenterY - mCircleRadius)); 52 | mPointDatas.get(0).y +=mCircleRadius/2f; 53 | mPointControlls.get(2).x -= 20.0; 54 | 55 | mPointControlls.get(3).y -= 80.0; 56 | mPointControlls.get(4).y -= 80.0; 57 | mPointControlls.get(5).x += 20.0; 58 | mPointDatas.get(1).x-=10; 59 | mPointDatas.get(3).x+=10; 60 | 61 | Path path = new Path(); 62 | path.moveTo(mPointDatas.get(0).x, mPointDatas.get(0).y); 63 | for (int i = 0; i < mPointDatas.size(); i++) { 64 | if (i == mPointDatas.size() - 1) { 65 | path.cubicTo(mPointControlls.get(2 * i).x, mPointControlls.get(2 * i).y, mPointControlls.get(2 * i + 1).x, mPointControlls.get(2 * i + 1).y, mPointDatas.get(0).x, mPointDatas.get(0).y); 66 | 67 | } else { 68 | path.cubicTo(mPointControlls.get(2 * i).x, mPointControlls.get(2 * i).y, mPointControlls.get(2 * i + 1).x, mPointControlls.get(2 * i + 1).y, mPointDatas.get(i + 1).x, mPointDatas.get(i + 1).y); 69 | } 70 | 71 | } 72 | Paint paint=getPaint(); 73 | paint.setStyle(Paint.Style.STROKE); 74 | paint.setStrokeWidth(getBorderWidth()); 75 | canvas.drawPath(path,paint); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/fragment/DuangSettingFragment.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.fragment; 2 | import android.os.Bundle; 3 | import android.preference.PreferenceFragment; 4 | import com.moe.LiveVisualizer.R; 5 | import android.preference.ListPreference; 6 | import android.preference.Preference; 7 | import android.content.Intent; 8 | import android.app.Activity; 9 | import java.io.InputStream; 10 | import java.io.FileNotFoundException; 11 | import java.io.OutputStream; 12 | import java.io.FileOutputStream; 13 | import java.io.File; 14 | import java.io.IOException; 15 | import android.os.Handler; 16 | import android.os.Looper; 17 | 18 | public class DuangSettingFragment extends PreferenceFragment implements ListPreference.OnPreferenceChangeListener 19 | { 20 | private ListPreference duang_screen; 21 | @Override 22 | public void onCreate(Bundle savedInstanceState) 23 | { 24 | // TODO: Implement this method 25 | super.onCreate(savedInstanceState); 26 | getPreferenceManager().setSharedPreferencesName("moe"); 27 | addPreferencesFromResource(R.xml.duang); 28 | duang_screen=(ListPreference) findPreference("duang_screen"); 29 | duang_screen.setOnPreferenceChangeListener(this); 30 | duang_screen.setSummary(duang_screen.getEntries()[duang_screen.findIndexOfValue(getPreferenceManager().getSharedPreferences().getString("duang_screen","0"))]); 31 | } 32 | 33 | @Override 34 | public boolean onPreferenceChange(Preference p1, Object p2) 35 | { 36 | switch(p1.getKey()){ 37 | case "duang_screen": 38 | if(p2.equals("4")){ 39 | startActivityForResult(new Intent(Intent.ACTION_GET_CONTENT).setType("image/*"),4832); 40 | return false; 41 | } 42 | duang_screen.setSummary(duang_screen.getEntries()[duang_screen.findIndexOfValue(p2.toString())]); 43 | break; 44 | } 45 | return true; 46 | } 47 | 48 | @Override 49 | public void onActivityResult(int requestCode, int resultCode, Intent data) 50 | { 51 | // TODO: Implement this method 52 | super.onActivityResult(requestCode, resultCode, data); 53 | if(requestCode==4832&&resultCode==Activity.RESULT_OK){ 54 | save(data); 55 | } 56 | } 57 | 58 | 59 | private void save(final Intent data){ 60 | new Thread(){ 61 | public void run(){ 62 | InputStream is=null; 63 | OutputStream os=null; 64 | try 65 | { 66 | is = getActivity().getContentResolver().openInputStream(data.getData()); 67 | os=new FileOutputStream(new File(getActivity().getExternalFilesDir(null),"duang")); 68 | int len=0; 69 | byte[] buffer=new byte[2048]; 70 | while((len=is.read(buffer))!=-1) 71 | os.write(buffer,0,len); 72 | os.flush(); 73 | new Handler(Looper.getMainLooper()).post(new Runnable(){ 74 | 75 | @Override 76 | public void run() 77 | { 78 | duang_screen.setSummary(duang_screen.getEntries()[4]); 79 | getPreferenceManager().getSharedPreferences().edit().putString("duang_screen","4").commit(); 80 | } 81 | }); 82 | } 83 | catch (Exception e) 84 | {}finally{ 85 | try 86 | { 87 | if (os != null) 88 | os.close(); 89 | } 90 | catch (IOException e) 91 | {} 92 | try 93 | { 94 | if (is != null) 95 | is.close(); 96 | } 97 | catch (IOException e) 98 | {} 99 | } 100 | } 101 | }.start(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 35 | 36 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 51 | 52 | 53 | 54 | 58 | 59 | 60 | 61 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 100 | 101 | 102 | 103 | 107 | 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/circle/CircleTriangleDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.circle; 2 | import com.moe.LiveVisualizer.internal.ImageDraw; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.graphics.Canvas; 5 | import android.graphics.Shader; 6 | import android.graphics.Bitmap; 7 | import android.util.TypedValue; 8 | import android.graphics.Paint; 9 | import android.graphics.SweepGradient; 10 | import android.graphics.PorterDuffXfermode; 11 | import android.graphics.PorterDuff; 12 | import android.graphics.LinearGradient; 13 | import android.graphics.PointF; 14 | import com.moe.LiveVisualizer.utils.ColorList; 15 | 16 | public class CircleTriangleDraw extends RingDraw 17 | { 18 | 19 | private float[] points; 20 | private int size; 21 | private float[] lines=new float[8]; 22 | public CircleTriangleDraw(ImageDraw draw) 23 | { 24 | super(draw); 25 | } 26 | 27 | @Override 28 | public int size() 29 | { 30 | // TODO: Implement this method 31 | return size; 32 | } 33 | 34 | @Override 35 | public void onSizeChanged() 36 | { 37 | final double length=Math.min(getEngine().getDisplayWidth(),getEngine().getDisplayHeight()) / 3 * Math.PI; 38 | try 39 | { 40 | size = (int)((length - getSpaceWidth()*2) / (getBorderWidth()*2 + getSpaceWidth()*2)); 41 | } 42 | catch (Exception e) 43 | {} 44 | try 45 | { 46 | size = size > getEngine().getFftSize() ?getEngine().getFftSize(): size; 47 | } 48 | catch (Exception e) 49 | {} 50 | } 51 | 52 | 53 | @Override 54 | public void onDraw(Canvas canvas, int color_mode) 55 | { 56 | super.onDraw(canvas,color_mode); 57 | drawCircleImage(canvas); 58 | 59 | } 60 | 61 | @Override 62 | public void drawGraph(double[] buffer, Canvas canvas, final int color_mode,boolean useMode) 63 | { 64 | PointF point=getPointF(); 65 | float radius=getRadius(); 66 | final float radialHeight=getDirection()==OUTSIDE?getBorderHeight():getRadius(); 67 | Paint paint=getPaint(); 68 | paint.setStrokeWidth(getBorderWidth()); 69 | float width=getBorderWidth()/2; 70 | //paint.setStrokeWidth(0); 71 | if ( points == null || points.length != size() ) 72 | points = new float[size()]; 73 | float degress_step=360f / size(); 74 | 75 | canvas.save(); 76 | final PointF center=getPointF(); 77 | //canvas.rotate(degress_step / 2.0f, center.x, center.y); 78 | for ( int i=0;i < points.length;i ++ ) 79 | { 80 | if(useMode) 81 | checkMode(color_mode,paint); 82 | float height=(float) (buffer[i] / 127d * radialHeight); 83 | if ( height < points[i] ) 84 | points[i]=Math.max(0,points[i]-(points[i]-height)*getInterpolator((points[i]-height)/points[i]*0.8f)*0.45f); 85 | else if(height>points[i]) 86 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height); 87 | height=points[i]; 88 | //if(paint.getStrokeCap()==Paint.Cap.ROUND){ 89 | lines[0]=point.x-width-getSpaceWidth()/2; 90 | lines[1]=point.y-radius; 91 | lines[2]=point.x; 92 | lines[3]=point.y-radius+(getDirection()==OUTSIDE?-height:height); 93 | System.arraycopy(lines,2,lines,4,2); 94 | lines[6]=point.x+width+getSpaceWidth()/2; 95 | lines[7]=point.y-radius; 96 | canvas.drawLines(lines, paint); 97 | //canvas.drawArc(point.x-radius,point.y-radius,point.x+radius,point.y+radius,0,360,false,paint); 98 | //}else{ 99 | //canvas.drawRect(point.x-paint.getStrokeWidth()/2, point.y-radius, point.x + paint.getStrokeWidth()/2, point.y -radius+(getDirection()==OUTSIDE?- height:height), paint); 100 | //} 101 | canvas.rotate(degress_step, center.x, center.y); 102 | //degress+=degress_step; 103 | } 104 | canvas.restore(); 105 | //paint.setStyle(Paint.Style.FILL); 106 | //paint.setStrokeWidth(width*2); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/duang/Snow.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.duang; 2 | import android.util.DisplayMetrics; 3 | import android.graphics.Canvas; 4 | import java.util.Random; 5 | import android.graphics.Path; 6 | import android.graphics.Paint; 7 | import android.graphics.Matrix; 8 | 9 | public class Snow extends Duang 10 | { 11 | private Path path; 12 | private Paint paint; 13 | private Matrix matrix=new Matrix(); 14 | private float windSpeed,speed; 15 | private boolean wind; 16 | public Snow(){ 17 | paint=new Paint(); 18 | paint.setColor(0xffffffff); 19 | path=new Path(); 20 | } 21 | 22 | @Override 23 | public void draw(Canvas canvas) 24 | { 25 | setOffsetY(getOffsetY()+speed); 26 | if(getOffsetX()<-getSize()||getOffsetX()>getMaxWidth()||getOffsetY()>getMaxHeight()){ 27 | path.offset(-getOffsetX(),-getOffsetY()); 28 | setOffsetY(-getSize()); 29 | setOffsetX(getRandom().nextInt(getMaxWidth())-getSize()); 30 | path.offset(getOffsetX(),getOffsetY()); 31 | } 32 | else if(getOffsetY()>-getSize()){ 33 | setOffsetX(getOffsetX()+(wind?windSpeed:-windSpeed)); 34 | path.offset(wind?windSpeed:-windSpeed,speed); 35 | canvas.drawPath(path,paint); 36 | }else 37 | path.offset(0,speed); 38 | } 39 | 40 | @Override 41 | public void random(Random random) 42 | { 43 | setOffsetX(random.nextInt((int)(getMaxWidth()-getSize()))); 44 | //setSize(random.nextFloat()*(getMaxSize()-getMinSize())+getMinSize()); 45 | if(isFirst()) 46 | setOffsetY(-random.nextInt(getMaxHeight())); 47 | else 48 | setOffsetY(-getSize()); 49 | float scale=getSize()/24; 50 | matrix.setScale(scale,scale); 51 | resetPath(); 52 | //随机生成风向 53 | wind=random.nextBoolean(); 54 | //根据尺寸计算风力 55 | windSpeed=random.nextFloat()*getWind(); 56 | //windSpeed=getSize()/getMaxSize()*getWind(); 57 | //根据尺寸计算下降速度 58 | speed=getSize()/getMaxSize()*getSpeed()/10+1; 59 | } 60 | private void resetPath(){ 61 | path.reset(); 62 | path.moveTo(20.79f,13.95f); 63 | path.lineTo(18.46f,14.57f); 64 | path.lineTo(16.46f,13.44f); 65 | path.lineTo(16.46f,10.56f);// 66 | path.lineTo(18.46f,9.43f); 67 | path.lineTo(20.79f,10.05f); 68 | path.lineTo(21.31f,8.12f); 69 | path.lineTo(19.54f,7.65f); 70 | path.lineTo(20,5.88f); 71 | path.lineTo(18.07f,5.36f); 72 | path.lineTo(17.45f,7.69f); 73 | path.lineTo(15.45f,8.82f); 74 | path.lineTo(13,7.38f); 75 | path.lineTo(13,5.12f);// 76 | path.lineTo(14.71f,3.41f); 77 | path.lineTo(13.29f,2f); 78 | path.lineTo(12,3.29f); 79 | path.lineTo(10.71f,2f); 80 | path.lineTo(9.29f,3.41f); 81 | path.lineTo(11,5.12f); 82 | path.lineTo(11,7.38f);// 83 | path.lineTo(8.5f,8.82f); 84 | path.lineTo(6.5f,7.69f); 85 | path.lineTo(5.92f,5.36f); 86 | path.lineTo(4,5.88f); 87 | path.lineTo(4.47f,7.65f); 88 | path.lineTo(2.7f,8.12f); 89 | path.lineTo(3.22f,10.05f); 90 | path.lineTo(5.55f,9.43f); 91 | path.lineTo(7.55f,10.56f); 92 | path.lineTo(7.55f,13.45f);// 93 | path.lineTo(5.55f,14.58f); 94 | path.lineTo(3.22f,13.96f); 95 | path.lineTo(2.7f,15.89f); 96 | path.lineTo(4.47f,16.36f); 97 | path.lineTo(4,18.12f); 98 | path.lineTo(5.93f,18.64f); 99 | path.lineTo(6.55f,16.31f); 100 | path.lineTo(8.55f,15.18f); 101 | path.lineTo(11,16.62f); 102 | path.lineTo(11,18.88f);// 103 | path.lineTo(9.29f,20.59f); 104 | path.lineTo(10.71f,22f); 105 | path.lineTo(12,20.71f); 106 | path.lineTo(13.29f,22f); 107 | path.lineTo(14.7f,20.59f); 108 | path.lineTo(13,18.88f); 109 | path.lineTo(13,16.62f);// 110 | path.lineTo(15.5f,15.17f); 111 | path.lineTo(17.5f,16.3f); 112 | path.lineTo(18.12f,18.63f); 113 | path.lineTo(20,18.12f); 114 | path.lineTo(19.53f,16.35f); 115 | path.lineTo(21.3f,15.88f); 116 | path.lineTo(20.79f,13.95f); 117 | path.moveTo(9.5f,10.56f); 118 | path.lineTo(12,9.11f); 119 | path.lineTo(14.5f,10.56f); 120 | path.lineTo(14.5f,13.44f);// 121 | path.lineTo(12,14.89f); 122 | path.lineTo(9.5f,13.44f); 123 | path.lineTo(9.5f,10.56f);// 124 | path.close(); 125 | path.transform(matrix); 126 | path.offset(getOffsetX(),getOffsetY()); 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /app/src/main/res/xml/setting.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 15 | 18 | 21 | 22 | 28 | 34 | 40 | 47 | 52 | 57 | 62 | 68 | 73 | 80 | 84 | 89 | 94 | 99 | 103 | 109 | 115 | 118 | 121 | 124 | 127 | 130 | 131 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/circle/CenterRadialDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.circle; 2 | import com.moe.LiveVisualizer.internal.ImageDraw; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.graphics.Canvas; 5 | import com.moe.LiveVisualizer.internal.OnColorSizeChangedListener; 6 | import android.graphics.Shader; 7 | import android.graphics.Bitmap; 8 | import android.graphics.PointF; 9 | import android.graphics.Paint; 10 | import android.graphics.SweepGradient; 11 | import android.graphics.PorterDuffXfermode; 12 | import android.graphics.LinearGradient; 13 | import android.graphics.PorterDuff; 14 | import android.util.TypedValue; 15 | import com.moe.LiveVisualizer.draw.CircleDraw; 16 | import com.moe.LiveVisualizer.utils.ColorList; 17 | 18 | public class CenterRadialDraw extends RingDraw 19 | { 20 | 21 | private float[] points; 22 | public CenterRadialDraw(ImageDraw draw){ 23 | super(draw); 24 | } 25 | /*@Override 26 | public void onDraw(Canvas canvas, int color_mode) 27 | { 28 | Paint paint=getP; 29 | paint.setStrokeCap(getRound()); 30 | paint.setStrokeWidth(borderWidth); 31 | switch(color_mode){ 32 | case 0: 33 | switch ( getEngine().getColorList().size() ) 34 | { 35 | case 0: 36 | paint.setColor(0xff39c5bb); 37 | drawGraph(getFft(), canvas,color_mode,false); 38 | break; 39 | case 1: 40 | paint.setColor(getEngine().getColorList().get(0)); 41 | drawGraph(getFft(), canvas,color_mode,false); 42 | break; 43 | default: 44 | final int layer=canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG); 45 | drawGraph(getFft(),canvas,color_mode,false); 46 | if ( shader == null ) 47 | shader = new SweepGradient(canvas.getWidth() / 2.0f, canvas.getHeight() / 2.0f, getEngine().getColorList().toArray(), null); 48 | if(shaderBuffer==null){ 49 | shaderBuffer=Bitmap.createBitmap(canvas.getWidth(),canvas.getHeight(),Bitmap.Config.ARGB_4444); 50 | Canvas shaderCanvas=new Canvas(shaderBuffer); 51 | paint.setShader(shader); 52 | shaderCanvas.drawRect(0,0,shaderCanvas.getWidth(),shaderCanvas.getHeight(),paint); 53 | paint.setShader(null); 54 | } 55 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 56 | //canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint); 57 | canvas.drawBitmap(shaderBuffer, 0, 0, paint); 58 | //paint.setShader(null); 59 | paint.setXfermode(null); 60 | canvas.restoreToCount(layer); 61 | //canvas.drawBitmap(src, 0, 0, paint); 62 | //src.recycle(); 63 | /*if ( shader == null ) 64 | shader = new SweepGradient(canvas.getWidth() / 2.0f, canvas.getHeight() / 2.0f, getEngine().getColorList().toArray(), null); 65 | paint.setShader(shader); 66 | drawLines(getFft(), canvas, false,color_mode); 67 | paint.setShader(null);*/ 68 | /*break; 69 | } 70 | break; 71 | case 1: 72 | case 2: 73 | case 4: 74 | drawGraph(getFft(),canvas,color_mode,true); 75 | break; 76 | case 3: 77 | int color=getColor(); 78 | paint.setColor(getEngine().getPreference().getBoolean("nenosync",false)?color:0xffffffff); 79 | paint.setShadowLayer(borderWidth,0,0,color); 80 | drawGraph(getFft(),canvas,color_mode,false); 81 | paint.setShadowLayer(0,0,0,0); 82 | break; 83 | } 84 | paint.reset(); 85 | }*/ 86 | 87 | 88 | @Override 89 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) 90 | { 91 | if(points==null||points.length!=size()) 92 | points=new float[size()]; 93 | Paint paint=getPaint(); 94 | paint.setStrokeWidth(getBorderWidth()); 95 | canvas.save(); 96 | PointF point=getPointF(); 97 | canvas.rotate(-90,point.x,point.y); 98 | float degress=360f/points.length; 99 | for(int i=0;i100?0:100-distance); 97 | } 98 | }catch(Exception e){ 99 | if(mVisualizer!=null){ 100 | if(mVisualizer.getEnabled()) 101 | mVisualizer.setEnabled(false); 102 | mVisualizer.release(); 103 | } 104 | initVisualizer(); 105 | } 106 | } 107 | break; 108 | } 109 | return true; 110 | } 111 | private void fill(double[] b) { 112 | for (int i=0;i < b.length;i++) 113 | b[i] = 0; 114 | } 115 | private double a(double data1, double data2) { 116 | double d=Math.hypot(data1, data2); 117 | d = Math.min(127,d>64?d*0.7d:d*1.3d); 118 | return d; 119 | } 120 | /*private double[] fft(byte[] wave) { 121 | wave[0]=0; 122 | wave[1]=0; 123 | for (int i = 0,j=0; i=Build.VERSION_CODES.LOLLIPOP?R.layout.seekbar_preference_material:R.layout.seekbar_preference,parent,false); 34 | return view; 35 | } 36 | 37 | @Override 38 | protected void onBindView(View view) 39 | { 40 | super.onBindView(view); 41 | final SeekBar seekbar=(SeekBar)view.findViewById(R.id.seekbar); 42 | seekbar.setOnSeekBarChangeListener(this); 43 | TextView tips=(TextView)view.findViewById(R.id.tips); 44 | seekbar.setTag(tips); 45 | ((View)view.findViewById(R.id.plus)).setOnClickListener(new View.OnClickListener(){ 46 | 47 | @Override 48 | public void onClick(View p1) 49 | { 50 | seekbar.setProgress(seekbar.getProgress()+1); 51 | onStopTrackingTouch(seekbar); 52 | } 53 | }); 54 | ((View)view.findViewById(R.id.minus)).setOnClickListener(new View.OnClickListener(){ 55 | 56 | @Override 57 | public void onClick(View p1) 58 | { 59 | seekbar.setProgress(seekbar.getProgress()-1); 60 | onStopTrackingTouch(seekbar); 61 | } 62 | }); 63 | seekbar.setMax(max); 64 | seekbar.setProgress(progress); 65 | tips.setText(seekbar.getProgress()+(unit!=null?unit.toString():"")); 66 | } 67 | public void setMax(int max){ 68 | this.max=max; 69 | notifyChanged(); 70 | } 71 | @Override 72 | public void onProgressChanged(SeekBar p1, int p2, boolean p3) 73 | { 74 | if(p1.getTag()!=null) 75 | ((TextView)p1.getTag()).setText(p2+(unit!=null?unit.toString():"")); 76 | } 77 | 78 | @Override 79 | public void onStartTrackingTouch(SeekBar p1) 80 | { 81 | // TODO: Implement this method 82 | } 83 | public void setUnit(CharSequence unit){ 84 | this.unit=unit; 85 | notifyChanged(); 86 | } 87 | 88 | @Override 89 | public void onStopTrackingTouch(SeekBar p1) 90 | { 91 | if(callChangeListener(p1.getProgress())){ 92 | if(shouldPersist()){ 93 | progress=p1.getProgress(); 94 | persistInt(p1.getProgress()); 95 | } 96 | } 97 | } 98 | 99 | @Override 100 | protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) 101 | { 102 | init=true; 103 | if(restorePersistedValue){ 104 | progress=getPersistedInt(defaultValue!=null?defaultValue:progress); 105 | } 106 | } 107 | 108 | @Override 109 | protected Object onGetDefaultValue(TypedArray a, int index) 110 | { 111 | progress=a.getInt(index,progress); 112 | return progress; 113 | } 114 | 115 | @Override 116 | public void setDefaultValue(Object defaultValue) 117 | { 118 | if(!init) 119 | progress=defaultValue==null?progress:(int)defaultValue; 120 | } 121 | 122 | @Override 123 | protected Parcelable onSaveInstanceState() 124 | { 125 | return new SavedState(super.onSaveInstanceState()); 126 | } 127 | 128 | @Override 129 | protected void onRestoreInstanceState(Parcelable state) 130 | { 131 | SavedState save=(SeekBarPreference.SavedState) state; 132 | super.onRestoreInstanceState(save.getSuperState()); 133 | max=save.max; 134 | progress=save.progress; 135 | unit=save.unit; 136 | 137 | } 138 | 139 | class SavedState extends BaseSavedState{ 140 | int max,progress; 141 | CharSequence unit; 142 | public SavedState(Parcelable parcel){ 143 | super(parcel); 144 | } 145 | public SavedState(Parcel parcel){ 146 | super(parcel); 147 | max=parcel.readInt(); 148 | progress=parcel.readInt(); 149 | unit=(CharSequence)parcel.readValue(CharSequence.class.getClassLoader()); 150 | } 151 | @Override 152 | public void writeToParcel(Parcel dest, int flags) 153 | { 154 | // TODO: Implement this method 155 | super.writeToParcel(dest, flags); 156 | dest.writeInt(SeekBarPreference.this.max); 157 | dest.writeInt(SeekBarPreference.this.progress); 158 | dest.writeValue(SeekBarPreference.this.unit); 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/line/LineChartDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.line; 2 | import android.graphics.Paint; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.graphics.Canvas; 5 | import android.graphics.Rect; 6 | import android.graphics.Bitmap; 7 | import android.graphics.PorterDuffXfermode; 8 | import android.graphics.PorterDuff; 9 | import android.graphics.LinearGradient; 10 | import android.util.TypedValue; 11 | import android.graphics.Shader; 12 | import com.moe.LiveVisualizer.internal.ImageDraw; 13 | import com.moe.LiveVisualizer.draw.LineDraw; 14 | import com.moe.LiveVisualizer.utils.ColorList; 15 | import android.graphics.RectF; 16 | import android.graphics.Path; 17 | 18 | public class LineChartDraw extends LineDraw 19 | { 20 | private float[] tmpData=new float[8]; 21 | private float[] pointX; 22 | private float[] points; 23 | public LineChartDraw(ImageDraw draw) 24 | { 25 | super(draw); 26 | } 27 | 28 | @Override 29 | public void notifySizeChanged() { 30 | super.notifySizeChanged(); 31 | if(pointX==null||pointX.length!=size()){ 32 | pointX=new float[size()]; 33 | float offsetX=getStartOffset(); 34 | for(int i=0;ipoints[i]) 117 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height*0.6f); 118 | } 119 | Path path = new Path(); 120 | path.moveTo(offsetX,getDrawHeight()); 121 | for (int i = 0; i < size(); i ++) { 122 | float startX=pointX[i]; 123 | float startY=points[i]; 124 | float endX,endY; 125 | if(i+1==size()){ 126 | endX=canvas.getWidth(); 127 | endY=getDrawHeight(); 128 | }else{ 129 | endX=pointX[i+1]; 130 | endY=points[i+1]; 131 | } 132 | float centerX=startX+(endX-startX)/2; 133 | float centerY=startY+(endY-startY)/2; 134 | path.quadTo(startX,startY,centerX,centerY); 135 | } 136 | path.lineTo(canvas.getWidth(),getDrawHeight()); 137 | if (useMode) 138 | checkMode(color_mode, paint); 139 | 140 | canvas.drawPath(path, paint); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/circle/RippleDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.circle; 2 | import android.graphics.Shader; 3 | import android.graphics.Bitmap; 4 | import android.graphics.PointF; 5 | import com.moe.LiveVisualizer.internal.ImageDraw; 6 | import com.moe.LiveVisualizer.service.LiveWallpaper; 7 | import android.util.TypedValue; 8 | import com.moe.LiveVisualizer.internal.OnColorSizeChangedListener; 9 | import android.graphics.Canvas; 10 | import android.graphics.Paint; 11 | import android.graphics.SweepGradient; 12 | import android.graphics.PorterDuffXfermode; 13 | import android.graphics.PorterDuff; 14 | import android.graphics.LinearGradient; 15 | import com.moe.LiveVisualizer.draw.CircleDraw; 16 | import com.moe.LiveVisualizer.utils.ColorList; 17 | 18 | public class RippleDraw extends RingDraw 19 | { 20 | private float[] points; 21 | //private float borderHeight,borderWidth; 22 | 23 | public RippleDraw(ImageDraw draw){ 24 | super(draw); 25 | } 26 | 27 | /*@Override 28 | public void onDraw(Canvas canvas, int color_mode) 29 | { 30 | Paint paint=getPaint() 31 | paint.setStrokeCap(getRound()); 32 | paint.setStrokeWidth(borderWidth); 33 | switch(color_mode){ 34 | case 0: 35 | switch ( getEngine().getColorList().size() ) 36 | { 37 | case 0: 38 | paint.setColor(0xff39c5bb); 39 | drawGraph(getFft(),canvas,color_mode,false); 40 | break; 41 | case 1: 42 | paint.setColor(getEngine().getColorList().get(0)); 43 | drawGraph(getFft(), canvas,color_mode,false); 44 | break; 45 | default: 46 | final int layer=canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG); 47 | drawGraph(getFft(),canvas,color_mode,false); 48 | paint.setStyle(Paint.Style.FILL); 49 | if ( shader == null ) 50 | shader = new SweepGradient(canvas.getWidth() / 2.0f, canvas.getHeight() / 2.0f, getEngine().getColorList().toArray(), null); 51 | if(shaderBuffer==null){ 52 | shaderBuffer=Bitmap.createBitmap(canvas.getWidth(),canvas.getHeight(),Bitmap.Config.ARGB_4444); 53 | Canvas shaderCanvas=new Canvas(shaderBuffer); 54 | paint.setShader(shader); 55 | shaderCanvas.drawRect(0,0,shaderCanvas.getWidth(),shaderCanvas.getHeight(),paint); 56 | paint.setShader(null); 57 | } 58 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 59 | //canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint); 60 | canvas.drawBitmap(shaderBuffer, 0, 0, paint); 61 | //paint.setShader(null); 62 | paint.setXfermode(null); 63 | canvas.restoreToCount(layer); 64 | //canvas.drawBitmap(src, 0, 0, paint); 65 | //src.recycle(); 66 | /*if ( shader == null ) 67 | shader = new SweepGradient(canvas.getWidth() / 2.0f, canvas.getHeight() / 2.0f, getEngine().getColorList().toArray(), null); 68 | paint.setShader(shader); 69 | drawLines(getFft(), canvas, false,color_mode); 70 | paint.setShader(null);*/ 71 | /*break; 72 | } 73 | break; 74 | case 1: 75 | case 4: 76 | case 2: 77 | drawGraph(getFft(),canvas,color_mode,true); 78 | break; 79 | case 3: 80 | int color=getColor(); 81 | paint.setColor(getEngine().getPreference().getBoolean("nenosync",false)?color:0xffffffff); 82 | paint.setShadowLayer(paint.getStrokeWidth(),0,0,color); 83 | drawGraph(getFft(),canvas,color_mode,false); 84 | paint.setShadowLayer(0,0,0,0); 85 | break; 86 | } 87 | paint.reset(); 88 | }*/ 89 | 90 | /*@Override 91 | public void onBorderWidthChanged(int width) 92 | { 93 | borderWidth=width; 94 | paint.setStrokeWidth(width); 95 | } 96 | 97 | @Override 98 | public void onBorderHeightChanged(int height) 99 | { 100 | borderHeight=height; 101 | } 102 | 103 | @Override 104 | public void onSpaceWidthChanged(int space) 105 | { 106 | 107 | } 108 | */ 109 | @Override 110 | public int size() 111 | { 112 | return 16; 113 | } 114 | 115 | @Override 116 | public void drawGraph(double[] buffer, Canvas canvas, int color_mode, boolean useMode) 117 | { 118 | if(points==null||points.length!=size()) 119 | points=new float[size()]; 120 | Paint paint=getPaint(); 121 | paint.setStyle(Paint.Style.STROKE); 122 | paint.setStrokeWidth(getBorderWidth()); 123 | PointF point=getPointF(); 124 | for(int i=0;ipoints[i]) 131 | points[i]=points[i]+(height-points[i])*getInterpolator((height-points[i])/height); 132 | height=points[i]; 133 | //if(paint.getStrokeCap()==Paint.Cap.ROUND) 134 | canvas.drawCircle(point.x,point.y,height,paint); 135 | //else 136 | // canvas.drawRect(point.x-paint.getStrokeWidth()/2,point.y-height,point.x+paint.getStrokeWidth()/2,point.y,paint); 137 | //canvas.rotate(degress,point.x,point.y) 138 | } 139 | 140 | //paint.setStyle(Paint.Style.FILL); 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/activity/CropActivity.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.activity; 2 | import android.app.Activity; 3 | import android.os.Bundle; 4 | import com.moe.LiveVisualizer.widget.CropView; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.graphics.BitmapFactory; 8 | import java.io.FileNotFoundException; 9 | import android.widget.Toast; 10 | import android.view.Menu; 11 | import android.view.MenuItem; 12 | import android.graphics.Bitmap; 13 | import android.os.Build; 14 | import android.Manifest; 15 | import android.content.pm.PackageManager; 16 | import java.io.OutputStream; 17 | import java.io.IOException; 18 | import android.graphics.Matrix; 19 | 20 | public class CropActivity extends Activity implements CropView.CropCallback 21 | { 22 | private CropView crop; 23 | private MenuItem cropItem; 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) 26 | { 27 | super.onCreate(savedInstanceState); 28 | setTitle("裁剪图片"); 29 | crop=new CropView(this); 30 | setContentView(crop); 31 | /* 32 | intent.putExtra("aspectX", display.getWidth()); 33 | intent.putExtra("aspectY", display.getHeight()); 34 | intent.putExtra("outputX",display.getWidth()); 35 | intent.putExtra("outputY",display.getHeight()); 36 | intent.putExtra("output", Uri.fromFile(wallpaper)); 37 | intent.putExtra("return-data",false); 38 | intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());*/ 39 | Intent intent=getIntent(); 40 | Uri uri=intent.getData(); 41 | try 42 | { 43 | crop.setImage(BitmapFactory.decodeStream(getContentResolver().openInputStream(uri))); 44 | } 45 | catch (Exception e) 46 | { 47 | Toast.makeText(getApplicationContext(),"无法读取文件",Toast.LENGTH_SHORT).show(); 48 | finish(); 49 | return; 50 | } 51 | crop.setCrop(intent.getIntExtra("aspectX",0),intent.getIntExtra("aspectY",0),intent.getBooleanExtra("two",false)); 52 | if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M&&checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED) 53 | requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},342); 54 | } 55 | 56 | @Override 57 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) 58 | { 59 | // TODO: Implement this method 60 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 61 | if(requestCode==342){ 62 | if(grantResults[0]!=PackageManager.PERMISSION_GRANTED) 63 | finish(); 64 | } 65 | } 66 | 67 | @Override 68 | public boolean onCreateOptionsMenu(Menu menu) 69 | { 70 | cropItem=menu.add(0,0,0,"裁剪"); 71 | cropItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); 72 | return true; 73 | } 74 | 75 | @Override 76 | public boolean onOptionsItemSelected(MenuItem item) 77 | { 78 | switch(item.getItemId()){ 79 | case android.R.id.home: 80 | finish(); 81 | break; 82 | case 0: 83 | if(item.getTitle().length()>2) 84 | break; 85 | item.setTitle("正在裁剪"); 86 | crop.crop(this); 87 | break; 88 | } 89 | return true; 90 | } 91 | 92 | @Override 93 | public void success(Bitmap b1, Bitmap b2) 94 | { 95 | if(b1!=null||b2!=null) 96 | if(getIntent().getBooleanExtra("return-data",false)){ 97 | Intent intent=new Intent(); 98 | intent.putExtra(Intent.EXTRA_STREAM,b1); 99 | setResult(RESULT_OK,intent); 100 | finish(); 101 | return; 102 | } 103 | int outputX=getIntent().getIntExtra("outputX",-1); 104 | int outputY=getIntent().getIntExtra("outputY",-1); 105 | b1=scale(b1,outputX,outputY); 106 | if( b1!=null&&getIntent().getParcelableExtra("output")!=null){ 107 | OutputStream os=null; 108 | try 109 | { 110 | os=getContentResolver().openOutputStream((Uri)getIntent().getParcelableExtra("output")); 111 | 112 | b1.compress(Bitmap.CompressFormat.valueOf((getIntent().getStringExtra("outputFormat")==null?Bitmap.CompressFormat.PNG.toString():getIntent().getStringExtra("outputFormat"))),100,os); 113 | os.flush(); 114 | } 115 | catch (Exception e) 116 | {}finally{ 117 | try 118 | { 119 | if ( os != null )os.close(); 120 | } 121 | catch (IOException e) 122 | {} 123 | } 124 | } 125 | b2=scale(b2,outputY,outputX); 126 | if( b2!=null&&getIntent().getParcelableExtra("output2")!=null){ 127 | OutputStream os=null; 128 | try 129 | { 130 | os=getContentResolver().openOutputStream((Uri)getIntent().getParcelableExtra("output2")); 131 | 132 | b2.compress(Bitmap.CompressFormat.valueOf((getIntent().getStringExtra("outputFormat")==null?Bitmap.CompressFormat.PNG.toString():getIntent().getStringExtra("outputFormat"))),100,os); 133 | os.flush(); 134 | } 135 | catch (Exception e) 136 | {}finally{ 137 | try 138 | { 139 | if ( os != null )os.close(); 140 | } 141 | catch (IOException e) 142 | {} 143 | } 144 | } 145 | setResult(RESULT_OK); 146 | finish(); 147 | } 148 | 149 | private Bitmap scale(Bitmap src,float width,float height){ 150 | if(src==null)return null; 151 | if(width<1||height<1)return src; 152 | float scaleX=width/src.getWidth(); 153 | float scaleY=height/src.getHeight(); 154 | Bitmap bit=Bitmap.createScaledBitmap(src,(int)(src.getWidth()*scaleX),(int)(src.getHeight()*scaleY),true); 155 | if(bit!=src) 156 | src.recycle(); 157 | return bit; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/duang/Engine.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.duang; 2 | import com.moe.LiveVisualizer.service.LiveWallpaper; 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import android.util.DisplayMetrics; 6 | import android.view.WindowManager; 7 | import android.app.Service; 8 | import android.graphics.Canvas; 9 | import java.util.Iterator; 10 | import java.lang.reflect.Constructor; 11 | import java.lang.reflect.InvocationTargetException; 12 | import android.content.Context; 13 | import android.graphics.Bitmap; 14 | import android.graphics.BitmapFactory; 15 | import java.io.File; 16 | 17 | public class Engine 18 | { 19 | private Class duang; 20 | private int wind,speed,maxSize,minSize; 21 | private List list; 22 | private LiveWallpaper.WallpaperEngine engine; 23 | private DisplayMetrics display=new DisplayMetrics(); 24 | private Bitmap buffer; 25 | private Engine(LiveWallpaper.WallpaperEngine engine){ 26 | this.engine=engine; 27 | wind=engine.getPreference().getInt("duang_wind",2); 28 | speed=engine.getPreference().getInt("duang_speed",30); 29 | maxSize=engine.getPreference().getInt("duang_maxSize",50); 30 | minSize=engine.getPreference().getInt("duang_minSize",10); 31 | changed(); 32 | list=new ArrayList<>(); 33 | setDuang(Integer.parseInt(engine.getPreference().getString("duang_screen","0"))); 34 | 35 | } 36 | 37 | public int getSpeed() 38 | { 39 | // TODO: Implement this method 40 | return speed; 41 | } 42 | 43 | public DisplayMetrics getDisplay() 44 | { 45 | // TODO: Implement this method 46 | return display; 47 | } 48 | 49 | public int getWind() 50 | { 51 | // TODO: Implement this method 52 | return wind; 53 | } 54 | 55 | public int getMxSize() 56 | { 57 | // TODO: Implement this method 58 | return maxSize; 59 | } 60 | 61 | public int getMinSize() 62 | { 63 | // TODO: Implement this method 64 | return minSize; 65 | } 66 | 67 | 68 | public Bitmap getBuffer() 69 | { 70 | return buffer; 71 | } 72 | public Context getContext(){ 73 | return engine.getContext(); 74 | } 75 | public static Engine init(LiveWallpaper.WallpaperEngine engine){ 76 | return new Engine(engine); 77 | } 78 | public void draw(Canvas canvas){ 79 | synchronized(list){ 80 | Iterator iterator=list.iterator(); 81 | while(iterator.hasNext()) 82 | iterator.next().draw(canvas); 83 | } 84 | } 85 | public void reset(){ 86 | Iterator iterator=list.iterator(); 87 | while(iterator.hasNext()) 88 | iterator.next().reset(false); 89 | } 90 | public void changed(){ 91 | ((WindowManager)engine.getContext().getSystemService(Service.WINDOW_SERVICE)).getDefaultDisplay().getRealMetrics(display); 92 | } 93 | public void setSizeChanged(int size){ 94 | synchronized(list){ 95 | if(size>list.size()){ 96 | for(int i=list.size();i iterator=list.iterator(); 186 | while(iterator.hasNext()) 187 | iterator.next().reset(true); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/LineDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw; 2 | import com.moe.LiveVisualizer.internal.ImageDraw; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.graphics.Paint; 5 | import android.graphics.Canvas; 6 | import android.graphics.PorterDuffXfermode; 7 | import android.graphics.PorterDuff; 8 | 9 | public abstract class LineDraw extends Draw { 10 | private int size; 11 | private float spaceWidth,borderHeight,borderWidth,drawHeight,sourceSpace,offsetX; 12 | private Paint paint; 13 | private boolean antialias; 14 | public LineDraw(ImageDraw draw) { 15 | super(draw); 16 | LiveWallpaper.WallpaperEngine engine=getEngine(); 17 | paint = new Paint(); 18 | //paint.setStyle(Paint.Style.FILL); 19 | //paint.setStrokeCap(getEngine().getPreference().getBoolean("round", true) ?Paint.Cap.ROUND: Paint.Cap.SQUARE); 20 | borderHeight = engine.getPreference().getInt("borderHeight", 100); 21 | sourceSpace = engine.getPreference().getInt("spaceWidth", 20); 22 | drawHeight = engine.getDisplayHeight() - engine.getPreference().getInt("height", 10) / 100.0f * engine.getDisplayHeight(); 23 | borderWidth = engine.getPreference().getInt("borderWidth", 30); 24 | size = engine.getPreference().getInt("num", 50); 25 | paint.setStrokeWidth(borderWidth); 26 | notifySizeChanged(); 27 | } 28 | 29 | @Override 30 | public void setAntialias(boolean antialias) { 31 | this.antialias = antialias; 32 | //paint.setAntiAlias(antialias); 33 | } 34 | @Override 35 | public void setNum(int num) { 36 | this.size = num; 37 | notifySizeChanged(); 38 | } 39 | 40 | public Paint getPaint() { 41 | return paint; 42 | } 43 | public float getDrawHeight() { 44 | return drawHeight; 45 | } 46 | public float getSpaceWidth() { 47 | return spaceWidth; 48 | } 49 | public float getBorderWidth() { 50 | return borderWidth; 51 | } 52 | public float getBorderHeight() { 53 | return borderHeight; 54 | } 55 | @Override 56 | final public void onDrawHeightChanged(float height) { 57 | this.drawHeight = height; 58 | } 59 | 60 | @Override 61 | final public void onBorderHeightChanged(int height) { 62 | this.borderHeight = height; 63 | notifySizeChanged(); 64 | } 65 | 66 | @Override 67 | public void draw(Canvas canvas) { 68 | paint.setStrokeWidth(borderWidth); 69 | paint.setStrokeCap(getRound()); 70 | paint.setStyle(Paint.Style.FILL); 71 | super.draw(canvas); 72 | } 73 | 74 | @Override 75 | public void onDraw(Canvas canvas, int color_mode) { 76 | if (isFinalized())return; 77 | Paint paint=getPaint(); 78 | paint.setStrokeCap(getRound()); 79 | paint.setAntiAlias(antialias); 80 | paint.setDither(antialias); 81 | switch (color_mode) { 82 | case 0: 83 | switch (getEngine().getColorList().size()) { 84 | case 0: 85 | paint.setColor(0xff39c5bb); 86 | drawGraph(getFft(), canvas, color_mode, false); 87 | break; 88 | case 1: 89 | paint.setColor(getEngine().getColorList().get(0)); 90 | drawGraph(getFft(), canvas, color_mode, false); 91 | break; 92 | default: 93 | paint.setShader(getShader()); 94 | drawGraph(getFft(), canvas, color_mode, false); 95 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 96 | paint.setShader(null); 97 | break; 98 | } 99 | break; 100 | case 1: 101 | case 2: 102 | if (getEngine() != null) 103 | switch (getEngine().getColorList().size()) { 104 | case 0: 105 | paint.setColor(0xff39c5bb); 106 | break; 107 | default: 108 | paint.setColor(getEngine().getColorList().get(0)); 109 | break; 110 | } 111 | case 4: 112 | drawGraph(getFft(), canvas, color_mode, true); 113 | break; 114 | case 3: 115 | int color=getColor(); 116 | try { 117 | paint.setColor(getEngine().getPreference().getBoolean("nenosync", false) ?color: 0xffffffff); 118 | } catch (NullPointerException e) {} 119 | paint.setShadowLayer(getBorderWidth(), 0, 0, color); 120 | drawGraph(getFft(), canvas, color_mode, false); 121 | paint.clearShadowLayer(); 122 | break; 123 | } 124 | paint.reset(); 125 | } 126 | 127 | 128 | 129 | 130 | 131 | @Override 132 | final public void onBorderWidthChanged(int width) { 133 | this.borderWidth = width; 134 | paint.setStrokeWidth(width); 135 | notifySizeChanged(); 136 | } 137 | 138 | @Override 139 | final public void onSpaceWidthChanged(int space) { 140 | sourceSpace = space; 141 | notifySizeChanged(); 142 | } 143 | @Override 144 | public int size() { 145 | return size; 146 | } 147 | 148 | @Override 149 | public void notifySizeChanged() { 150 | /*try 151 | { 152 | size = (int)(getEngine().getDisplayWidth()/sourceSpace); 153 | } 154 | catch (Exception e) 155 | {} 156 | try 157 | { 158 | size = size > getEngine().getFftSize() ?getEngine().getFftSize(): size; 159 | spaceWidth = (float)getEngine().getDisplayWidth()/(size-1); 160 | 161 | } 162 | catch (Exception e) 163 | {}*/ 164 | spaceWidth=getEngine().getDisplayWidth()/(float)size; 165 | offsetX=(getSpaceWidth()-getBorderWidth())/2f; 166 | } 167 | 168 | @Override 169 | public void finalized() { 170 | // TODO: Implement this method 171 | super.finalized(); 172 | paint.reset(); 173 | } 174 | public float getStartOffset(){ 175 | return offsetX; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/Draw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw; 2 | import com.moe.LiveVisualizer.internal.ImageDraw; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.graphics.Canvas; 5 | import android.graphics.Shader; 6 | import com.moe.LiveVisualizer.service.LiveWallpaper.WallpaperEngine; 7 | import android.graphics.Color; 8 | import android.animation.ValueAnimator; 9 | import android.animation.ObjectAnimator; 10 | import android.os.Handler; 11 | import android.os.Looper; 12 | import android.os.Message; 13 | import android.animation.TypeEvaluator; 14 | import android.animation.PropertyValuesHolder; 15 | import android.graphics.Matrix; 16 | import android.graphics.Paint; 17 | import android.animation.ArgbEvaluator; 18 | import com.moe.LiveVisualizer.utils.ColorList; 19 | 20 | abstract class Draw implements com.moe.LiveVisualizer.inter.Draw { 21 | private boolean round,finalize; 22 | private int[] fade=new int[2]; 23 | private Handler handler; 24 | private int index,color_step; 25 | private ImageDraw draw; 26 | private ValueAnimator anime; 27 | private LiveWallpaper.WallpaperEngine engine; 28 | private boolean isInterval; 29 | private ArgbEvaluator argb; 30 | Draw(ImageDraw draw) { 31 | 32 | this.draw = draw; 33 | this.engine = draw.getEngine(); 34 | round = engine.getPreference().getBoolean("round", false); 35 | 36 | } 37 | 38 | @Override 39 | final public void setRound(boolean round) { 40 | this.round = round; 41 | } 42 | 43 | public Paint.Cap getRound() { 44 | return round ?Paint.Cap.ROUND: Paint.Cap.SQUARE; 45 | } 46 | @Override 47 | public LiveWallpaper.WallpaperEngine getEngine() { 48 | return engine; 49 | } 50 | 51 | @Override 52 | public double[] getFft() { 53 | return draw.getFft(); 54 | } 55 | 56 | @Override 57 | public byte[] getWave() { 58 | return draw.getWave(); 59 | } 60 | 61 | @Override 62 | public Shader getShader() { 63 | return draw.getShader(); 64 | } 65 | 66 | @Override 67 | public int getColor() { 68 | if (handler == null) { 69 | handler = new Handler(Looper.getMainLooper(), new Handler.Callback(){ 70 | 71 | @Override 72 | public boolean handleMessage(Message p1) { 73 | anime.start(); 74 | return false; 75 | } 76 | }); 77 | argb = new ArgbEvaluator(); 78 | anime = new ValueAnimator(); 79 | anime.setRepeatCount(0); 80 | anime.setIntValues(0); 81 | anime.setRepeatMode(ValueAnimator.RESTART); 82 | } 83 | switch (engine.getColorList().size()) { 84 | case 0: 85 | return 0xff39c5bb; 86 | case 1: 87 | return engine.getColorList().get(0); 88 | default: 89 | if (anime.isRunning()) { 90 | if (isInterval) 91 | return fade[0]; 92 | else 93 | return evaluate(anime.getAnimatedFraction(), fade); 94 | } else if (isInterval) { 95 | //进入渐变 96 | int readyIndex=index + 1; 97 | if (readyIndex >= engine.getColorList().size()) 98 | readyIndex = 0; 99 | fade[0] = engine.getColorList().get(index); 100 | fade[1] = engine.getColorList().get(readyIndex); 101 | anime.setDuration(getEngine().getPreference().getInt("nenofade", 2) * 1000); 102 | isInterval = false; 103 | handler.sendEmptyMessage(0); 104 | 105 | } else { 106 | index++; 107 | if (index >= engine.getColorList().size()) 108 | index = 0; 109 | fade[0] = (engine.getColorList().get(index)); 110 | isInterval = true; 111 | anime.setDuration(getEngine().getPreference().getInt("nenointerval", 5) * 1000); 112 | handler.sendEmptyMessage(0); 113 | } 114 | return fade[0]; 115 | } 116 | } 117 | 118 | @Override 119 | public float getInterpolator(float interpolator) { 120 | if (draw == null)return interpolator; 121 | return draw.getInterpolation(interpolator); 122 | } 123 | 124 | 125 | public void draw(Canvas canvas) { 126 | color_step = 0; 127 | if (draw != null) 128 | onDraw(canvas, Integer.parseInt(draw.getColorMode())); 129 | } 130 | 131 | public Integer evaluate(float fraction, int... n) { 132 | return (Integer)argb.evaluate(fraction, n[0], n[1]); 133 | /*int p2=n[0]; 134 | int p3=n[1]; 135 | int startA=Color.alpha(p2); 136 | int endA=Color.alpha(p3); 137 | int startRed = Color.red(p2); 138 | int startGreen = Color.green(p2); 139 | int startBlue = Color.blue(p2); 140 | int endRed = Color.red(p3); 141 | int endGreen = Color.green(p3); 142 | int endBlue = Color.blue(p3); 143 | 144 | int alpha=getCurrentColor(startA,endA,fraction); 145 | int red=getCurrentColor(startRed,endRed,fraction); 146 | int green=getCurrentColor(startGreen,endGreen,fraction); 147 | int blue=getCurrentColor(startBlue,endBlue,fraction); 148 | 149 | return Color.argb(alpha,red,green,blue);*/ 150 | } 151 | 152 | /*private int getCurrentColor(int start, int end,float fraction) { 153 | return start-(int)((start-end)*fraction); 154 | }*/ 155 | 156 | 157 | 158 | 159 | @Override 160 | public void setOffsetX(int x) { 161 | // TODO: Implement this method 162 | } 163 | 164 | @Override 165 | public void setOffsetY(int y) { 166 | // TODO: Implement this method 167 | } 168 | 169 | @Override 170 | public void finalized() { 171 | draw = null; 172 | anime = null; 173 | engine = null; 174 | finalize = true; 175 | } 176 | 177 | @Override 178 | public boolean isFinalized() { 179 | // TODO: Implement this method 180 | return finalize; 181 | } 182 | 183 | @Override 184 | protected void finalize() throws Throwable { 185 | super.finalize(); 186 | finalized(); 187 | } 188 | 189 | @Override 190 | public void checkMode(int mode, Paint paint) { 191 | final LiveWallpaper.WallpaperEngine engine=getEngine(); 192 | if (getEngine() == null)return; 193 | final ColorList colorList=engine.getColorList(); 194 | if (colorList == null)return; 195 | switch (mode) { 196 | case 1: 197 | paint.setColor(colorList.get(color_step)); 198 | color_step++; 199 | if (color_step >= colorList.size()) 200 | color_step = 0; 201 | 202 | break; 203 | case 2: 204 | paint.setColor(0xff000000 | (int)(Math.random() * 0xffffff)); 205 | break; 206 | case 4: 207 | int color=colorList.get(color_step); 208 | paint.setColor(engine.getPreference().getBoolean("nenosync", false) ?color: 0xffffffff); 209 | color_step++; 210 | if (color_step >= colorList.size()) 211 | color_step = 0; 212 | paint.setShadowLayer(paint.getStrokeWidth(), 0, 0, color); 213 | break; 214 | } 215 | } 216 | 217 | 218 | } 219 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/draw/circle/RingDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.draw.circle; 2 | import com.moe.LiveVisualizer.internal.ImageDraw; 3 | import com.moe.LiveVisualizer.service.LiveWallpaper; 4 | import android.graphics.Paint; 5 | import android.graphics.Canvas; 6 | import android.graphics.PointF; 7 | import android.graphics.Bitmap; 8 | import android.graphics.Matrix; 9 | import android.graphics.PorterDuffXfermode; 10 | import android.graphics.PorterDuff; 11 | import com.moe.LiveVisualizer.internal.OnColorSizeChangedListener; 12 | import android.graphics.Shader; 13 | import android.util.TypedValue; 14 | import com.moe.LiveVisualizer.draw.CircleDraw; 15 | import com.moe.LiveVisualizer.internal.ImageThread; 16 | import android.graphics.SweepGradient; 17 | 18 | public abstract class RingDraw extends CircleDraw implements OnColorSizeChangedListener 19 | { 20 | public final static int OUTSIDE=0; 21 | public final static int INSIDE=1; 22 | private int direction; 23 | private Paint paint; 24 | private float degress=0,vDegress=0; 25 | private float radius,degress_step;//圆形半径 26 | private boolean cutCenterImage,antialias; 27 | private ImageDraw draw; 28 | private Shader shader; 29 | private Bitmap shaderBuffer; 30 | private int borderHeight,size; 31 | private float spaceWidth,borderWidth; 32 | 33 | public RingDraw(ImageDraw draw){ 34 | super(draw); 35 | LiveWallpaper.WallpaperEngine engine=getEngine(); 36 | this.draw=draw; 37 | borderHeight = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, engine.getPreference().getInt("borderHeight", 100), engine.getContext().getResources().getDisplayMetrics()); 38 | spaceWidth = engine.getPreference().getInt("spaceWidth", 20); 39 | direction=Integer.parseInt(engine.getPreference().getString("direction",OUTSIDE+"")); 40 | paint = new Paint(); 41 | //paint.setStrokeCap(getEngine().getPreference().getBoolean("round",true)?Paint.Cap.ROUND:Paint.Cap.SQUARE); 42 | paint.setColor(0xff39c5bb); 43 | borderWidth=(engine.getPreference().getInt("borderWidth",30)); 44 | radius=engine.getPreference().getInt("circleRadius",Math.min(engine.getDisplayWidth(),engine.getDisplayHeight())/6); 45 | cutCenterImage=engine.getPreference().getBoolean("cutImage",true); 46 | degress_step=engine.getPreference().getInt("degress",10)/100f*10; 47 | engine.registerColorSizeChangedListener(this); 48 | onSizeChanged(); 49 | } 50 | 51 | @Override 52 | public void setAntialias(boolean antialias) 53 | { 54 | this.antialias=antialias; 55 | //paint.setAntiAlias(antialias); 56 | } 57 | 58 | 59 | public float getBorderHeight(){ 60 | return borderHeight; 61 | } 62 | public float getSpaceWidth(){ 63 | return spaceWidth; 64 | } 65 | @Override 66 | public void onBorderHeightChanged(int height) 67 | { 68 | borderHeight = height; 69 | } 70 | 71 | @Override 72 | public void notifySizeChanged() 73 | { 74 | super.notifySizeChanged(); 75 | shader=null; 76 | if(shaderBuffer!=null) 77 | shaderBuffer.recycle(); 78 | shaderBuffer=null; 79 | onSizeChanged(); 80 | } 81 | 82 | @Override 83 | public void onSpaceWidthChanged(int space) 84 | { 85 | spaceWidth = space; 86 | onSizeChanged(); 87 | } 88 | 89 | @Override 90 | public void setNum(int num) { 91 | super.setNum(num); 92 | onSizeChanged(); 93 | } 94 | 95 | @Override 96 | public int size() 97 | { 98 | return super.getSize(); 99 | } 100 | public void onSizeChanged() 101 | { 102 | try 103 | { 104 | size = (int)(2*getRadius()*Math.PI/spaceWidth); 105 | } 106 | catch (Exception e) 107 | {} 108 | try 109 | { 110 | size = size > getEngine().getFftSize() ?getEngine().getFftSize(): size; 111 | } 112 | catch (Exception e) 113 | {} 114 | 115 | } 116 | 117 | @Override 118 | public void onBorderWidthChanged(int width) 119 | { 120 | this.borderWidth=width; 121 | onSizeChanged(); 122 | } 123 | public float getBorderWidth(){ 124 | return borderWidth; 125 | } 126 | public void setShader(Shader shader) 127 | { 128 | this.shader = shader; 129 | } 130 | 131 | public Shader getShader() 132 | { 133 | return shader; 134 | } 135 | 136 | public Bitmap getShaderBuffer(int width,int height) 137 | { 138 | if(!isFinalized()&&shaderBuffer==null){ 139 | if(shader==null) 140 | shader=new SweepGradient(getPointF().x, getPointF().y, getEngine().getColorList().toArray(), null); 141 | shaderBuffer= Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); 142 | Canvas shaderCanvas=new Canvas(shaderBuffer); 143 | paint.reset(); 144 | paint.setShader(getShader()); 145 | shaderCanvas.drawRect(0, 0, shaderCanvas.getWidth(), shaderCanvas.getHeight(), paint); 146 | paint.reset(); 147 | } 148 | return shaderBuffer; 149 | } 150 | public Matrix getCenterScale() 151 | { 152 | if(draw==null) 153 | return null; 154 | return draw.getCenterScale(); 155 | } 156 | 157 | public void setDirection(int direction){ 158 | this.direction=direction; 159 | } 160 | public int getDirection(){ 161 | return direction; 162 | } 163 | public void setRadius(int radius) 164 | { 165 | this.radius=radius; 166 | } 167 | public void setDegressStep(float step){ 168 | degress_step=step; 169 | } 170 | 171 | final public void setCutImage(boolean cut) 172 | { 173 | cutCenterImage=cut; 174 | } 175 | final public Paint getPaint(){ 176 | return paint; 177 | } 178 | 179 | @Override 180 | public void onDraw(Canvas canvas, int color_mode) throws NullPointerException 181 | { 182 | if(isFinalized())return; 183 | int count=-1; 184 | if(isVisualizerRotation()){ 185 | count=canvas.save(); 186 | canvas.rotate(vDegress+=degress_step,getPointF().x,getPointF().y); 187 | if(vDegress>=360)vDegress=0; 188 | } 189 | Paint paint=getPaint(); 190 | paint.setStrokeCap(getRound()); 191 | paint.setAntiAlias(antialias); 192 | paint.setDither(antialias); 193 | switch(color_mode){ 194 | case 0: 195 | switch ( getEngine().getColorList().size() ) 196 | { 197 | case 0: 198 | paint.setColor(0xff39c5bb); 199 | drawGraph(getFft(), canvas, color_mode,false); 200 | break; 201 | case 1: 202 | paint.setColor(getEngine().getColorList().get(0)); 203 | drawGraph(getFft(), canvas, color_mode,false); 204 | break; 205 | default: 206 | final int layer=canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG); 207 | drawGraph(getFft(), canvas, color_mode,false); 208 | paint.reset(); 209 | Bitmap buffer=getShaderBuffer(canvas.getWidth(),canvas.getHeight()); 210 | if(buffer!=null&&!buffer.isRecycled()){ 211 | //paint.setStyle(Paint.Style.FILL); 212 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 213 | canvas.drawBitmap(buffer, 0, 0, paint); 214 | //paint.setXfermode(null); 215 | } 216 | canvas.restoreToCount(layer); 217 | break; 218 | } 219 | break; 220 | case 1: 221 | case 2: 222 | if(getEngine()!=null) 223 | switch ( getEngine().getColorList().size() ) 224 | { 225 | case 0: 226 | paint.setColor(0xff39c5bb); 227 | break; 228 | default: 229 | paint.setColor(getEngine().getColorList().get(0)); 230 | break; 231 | } 232 | case 4: 233 | drawGraph(getFft(), canvas, color_mode,true); 234 | break; 235 | case 3: 236 | int color=getColor(); 237 | try{ 238 | paint.setColor(getEngine().getPreference().getBoolean("nenosync",false)?color:0xffffffff); 239 | }catch(NullPointerException e){} 240 | paint.setShadowLayer(getBorderWidth(),0,0,color); 241 | drawGraph(getFft(), canvas, color_mode,false); 242 | paint.clearShadowLayer(); 243 | break; 244 | } 245 | paint.reset(); 246 | if(count!=-1) 247 | canvas.restoreToCount(count); 248 | } 249 | 250 | 251 | public void drawCircleImage(Canvas canvas){ 252 | final LiveWallpaper.WallpaperEngine engine=getEngine(); 253 | if(engine==null)return; 254 | final ImageThread image=engine.getCircleImage(); 255 | if(image==null)return; 256 | final Bitmap circle=image.getImage(); 257 | if(circle==null||circle.isRecycled())return; 258 | final int layer=canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,canvas.ALL_SAVE_FLAG); 259 | PointF point=getPointF(); 260 | //canvas.drawColor(0xffffffff); 261 | if(engine.getPreference().getBoolean("circleSwitch",true)){ 262 | degress+=degress_step; 263 | if ( degress >= 360 )degress = 0; 264 | } 265 | canvas.rotate(degress,point.x,point.y); 266 | if(getCenterScale()!=null){ 267 | Matrix matrix=getCenterScale(); 268 | float scale=Math.max(radius*2/circle.getWidth(),radius*2/circle.getHeight()); 269 | matrix.setScale(scale,scale); 270 | matrix.postTranslate(point.x-circle.getWidth()*scale/2,point.y-circle.getHeight()*scale/2); 271 | } 272 | try{ 273 | if(cutCenterImage){ 274 | canvas.drawCircle(point.x,point.y, radius, paint); 275 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 276 | if(getCenterScale()!=null) 277 | canvas.drawBitmap(circle,getCenterScale(),paint); 278 | else 279 | canvas.drawBitmap(circle,point.x-circle.getWidth()/2,point.y-circle.getHeight()/2, paint); 280 | paint.setXfermode(null); 281 | }else{ 282 | if(getCenterScale()!=null) 283 | canvas.drawBitmap(circle,getCenterScale(),paint); 284 | else 285 | canvas.drawBitmap(circle,point.x-circle.getWidth()/2,point.y-circle.getHeight()/2, paint); 286 | } 287 | }catch(Exception e){} 288 | canvas.restoreToCount(layer); 289 | } 290 | public float getRadius(){ 291 | return radius; 292 | } 293 | 294 | @Override 295 | public void finalized() 296 | { 297 | draw=null; 298 | onColorSizeChanged(); 299 | if(getEngine()!=null) 300 | getEngine().unRegisterOnColorSizeChanged(this); 301 | paint.reset(); 302 | super.finalized(); 303 | 304 | } 305 | @Override 306 | public void onColorSizeChanged() 307 | { 308 | shader = null; 309 | if ( shaderBuffer != null ) 310 | shaderBuffer.recycle(); 311 | shaderBuffer = null; 312 | } 313 | 314 | @Override 315 | public void setOffsetX(int x) 316 | { 317 | // TODO: Implement this method 318 | super.setOffsetX(x); 319 | onColorSizeChanged(); 320 | } 321 | 322 | @Override 323 | public void setOffsetY(int y) 324 | { 325 | // TODO: Implement this method 326 | super.setOffsetY(y); 327 | onColorSizeChanged(); 328 | } 329 | 330 | } 331 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/activity/SettingActivity.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.activity; 2 | import android.app.Activity; 3 | import android.os.Bundle; 4 | import android.app.Fragment; 5 | import android.content.Intent; 6 | import android.app.WallpaperManager; 7 | import android.content.ComponentName; 8 | import android.app.WallpaperInfo; 9 | import android.widget.Toast; 10 | import android.net.Uri; 11 | import android.view.MenuItem; 12 | import android.content.ActivityNotFoundException; 13 | import android.provider.Settings; 14 | import android.content.pm.PermissionInfo; 15 | import android.content.pm.PermissionGroupInfo; 16 | import android.content.pm.PackageManager; 17 | import android.os.Build; 18 | import android.app.AlertDialog; 19 | import android.content.DialogInterface; 20 | import android.view.Menu; 21 | import com.moe.LiveVisualizer.R; 22 | import com.moe.LiveVisualizer.service.LiveWallpaper; 23 | import com.moe.LiveVisualizer.fragment.SettingFragment; 24 | import com.moe.LiveVisualizer.fragment.CircleSettingFragment; 25 | import com.moe.LiveVisualizer.fragment.DuangSettingFragment; 26 | import android.content.SharedPreferences; 27 | import android.content.ContentValues; 28 | import android.widget.FrameLayout; 29 | import android.view.Window; 30 | 31 | public class SettingActivity extends Activity implements SharedPreferences.OnSharedPreferenceChangeListener 32 | { 33 | private MenuItem centerCircle,duang; 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) 36 | { 37 | super.onCreate(savedInstanceState); 38 | if (Intent.ACTION_MAIN.equals(getIntent().getAction())) 39 | init(); 40 | else 41 | { 42 | Toast.makeText(this, "别点了,进不来的", Toast.LENGTH_SHORT).show(); 43 | finish();} 44 | } 45 | private void init() 46 | { 47 | ComponentName service=new ComponentName(this, LiveWallpaper.class); 48 | if (Build.VERSION.SDK_INT < 23 || checkSelfPermission("android.permission.RECORD_AUDIO") == PackageManager.PERMISSION_GRANTED) 49 | { 50 | /*if ( Build.VERSION.SDK_INT > 18 && !notificationListenerEnable() ) 51 | { 52 | gotoNotificationAccessSetting(); 53 | return; 54 | }*/ 55 | if (getPackageManager().getComponentEnabledSetting(service) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED) 56 | { 57 | getPackageManager().setComponentEnabledSetting(service, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); 58 | } 59 | WallpaperInfo info=((WallpaperManager)getSystemService(WALLPAPER_SERVICE)).getWallpaperInfo(); 60 | if (info == null || !getPackageName().equals(info.getPackageName())) 61 | { 62 | Toast.makeText(getApplicationContext(), "先激活动态壁纸才能继续使用", Toast.LENGTH_LONG).show(); 63 | try 64 | { 65 | Intent intent =new Intent( 66 | WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER); 67 | intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, 68 | new ComponentName(this, LiveWallpaper.class)); 69 | startActivity(intent); 70 | } 71 | catch (Exception e1) 72 | { 73 | try 74 | { 75 | startActivity(new Intent(WallpaperManager.ACTION_LIVE_WALLPAPER_CHOOSER)); 76 | } 77 | catch (Exception e) 78 | { 79 | AlertDialog dialog= new AlertDialog.Builder(this).setMessage("无法打开动态壁纸设置界面,你仍然可以通过设置来启用").create(); 80 | dialog.setOnDismissListener(new DialogInterface.OnDismissListener(){ 81 | 82 | @Override 83 | public void onDismiss(DialogInterface p1) 84 | { 85 | // TODO: Implement this method 86 | finish(); 87 | } 88 | }); 89 | dialog.show(); 90 | } 91 | 92 | } 93 | finish(); 94 | } 95 | else 96 | { 97 | FrameLayout frame=new FrameLayout(this); 98 | frame.setFitsSystemWindows(true); 99 | frame.setId(android.R.id.widget_frame); 100 | ((FrameLayout)findViewById(android.R.id.content)).addView(frame); 101 | Fragment setting=getFragmentManager().findFragmentByTag("setting"); 102 | if (setting == null) 103 | { 104 | setting = new SettingFragment(); 105 | if (setting.isAdded()) 106 | getFragmentManager().beginTransaction().show(setting).commit(); 107 | else 108 | getFragmentManager().beginTransaction().add(android.R.id.widget_frame, setting, "setting").show(setting).commit(); 109 | } 110 | if(getActionBar()!=null){ 111 | getActionBar().setDisplayHomeAsUpEnabled(true); 112 | getActionBar().setHomeButtonEnabled(true); 113 | } 114 | getSharedPreferences("moe",0).registerOnSharedPreferenceChangeListener(this); 115 | } 116 | } 117 | else 118 | { 119 | if (getPackageManager().getComponentEnabledSetting(service) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED) 120 | { 121 | getPackageManager().setComponentEnabledSetting(service, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 122 | } 123 | requestPermissions(new String[]{"android.permission.RECORD_AUDIO","android.permission.READ_PHONE_STATE"}, 432); 124 | } 125 | } 126 | 127 | @Override 128 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) 129 | { 130 | // TODO: Implement this method 131 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 132 | if (requestCode == 432) 133 | { 134 | boolean flag=true; 135 | for (int grant:grantResults) 136 | { 137 | if (grant == PackageManager.PERMISSION_DENIED) 138 | flag = false; 139 | break; 140 | } 141 | if (flag) 142 | init(); 143 | else 144 | { 145 | Toast.makeText(getApplicationContext(), "未给权限,已退出", Toast.LENGTH_LONG).show(); 146 | finish(); 147 | } 148 | } 149 | } 150 | 151 | @Override 152 | public boolean onCreateOptionsMenu(Menu menu) 153 | { 154 | centerCircle = menu.add(0, 0, 0, "中心圆"); 155 | centerCircle.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); 156 | duang=menu.add(1,1,1,"屏幕特效"); 157 | duang.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); 158 | Fragment fragment=getFragmentManager().findFragmentByTag("setting"); 159 | centerCircle.setVisible(fragment != null && !fragment.isHidden()); 160 | duang.setVisible(fragment!=null&&!fragment.isHidden()); 161 | return true; 162 | } 163 | 164 | 165 | 166 | 167 | 168 | @Override 169 | public boolean onOptionsItemSelected(MenuItem item) 170 | { 171 | switch (item.getItemId()) 172 | { 173 | case android.R.id.home: 174 | onBackPressed(); 175 | return true; 176 | case 0: 177 | centerCircle.setVisible(false); 178 | duang.setVisible(false); 179 | Fragment circle_setting=getFragmentManager().findFragmentByTag("circle_setting"); 180 | if (circle_setting == null)circle_setting = new CircleSettingFragment(); 181 | if (circle_setting.isAdded()) 182 | getFragmentManager().beginTransaction().hide(getFragmentManager().findFragmentByTag("setting")).show(circle_setting).commit(); 183 | else 184 | getFragmentManager().beginTransaction().hide(getFragmentManager().findFragmentByTag("setting")).add(android.R.id.widget_frame, circle_setting, "circle_setting").commit(); 185 | 186 | return true; 187 | case 1: 188 | centerCircle.setVisible(false); 189 | duang.setVisible(false); 190 | Fragment duang_setting=getFragmentManager().findFragmentByTag("daung_setting"); 191 | if (duang_setting == null)duang_setting = new DuangSettingFragment(); 192 | if (duang_setting.isAdded()) 193 | getFragmentManager().beginTransaction().hide(getFragmentManager().findFragmentByTag("setting")).show(duang_setting).commit(); 194 | else 195 | getFragmentManager().beginTransaction().hide(getFragmentManager().findFragmentByTag("setting")).add(android.R.id.widget_frame, duang_setting, "duang_setting").commit(); 196 | 197 | break; 198 | } 199 | return super.onOptionsItemSelected(item); 200 | } 201 | 202 | @Override 203 | public void onBackPressed() 204 | { 205 | Fragment circle_setting=getFragmentManager().findFragmentByTag("circle_setting"); 206 | Fragment duang_setting=getFragmentManager().findFragmentByTag("duang_setting"); 207 | if (circle_setting != null && !circle_setting.isHidden()) 208 | { 209 | getFragmentManager().beginTransaction().hide(circle_setting).show(getFragmentManager().findFragmentByTag("setting")).commit(); 210 | if (centerCircle != null)centerCircle.setVisible(true); 211 | if(duang!=null)duang.setVisible(true); 212 | } 213 | else if(duang_setting!=null&&!duang_setting.isHidden()){ 214 | getFragmentManager().beginTransaction().hide(duang_setting).show(getFragmentManager().findFragmentByTag("setting")).commit(); 215 | if (centerCircle != null)centerCircle.setVisible(true); 216 | if(duang!=null)duang.setVisible(true); 217 | }else 218 | super.onBackPressed(); 219 | } 220 | 221 | @Override 222 | public void onSharedPreferenceChanged(SharedPreferences p1, String p2) 223 | { 224 | Uri.Builder build=new Uri.Builder(); 225 | build.scheme("content").authority("moe").path("moe").appendQueryParameter("key",p2).appendQueryParameter("value",p1.getAll().get(p2)+""); 226 | getContentResolver().update(build.build(),new ContentValues(),null,null); 227 | } 228 | 229 | @Override 230 | public void finish() 231 | { 232 | // TODO: Implement this method 233 | super.finish(); 234 | getSharedPreferences("moe",0).unregisterOnSharedPreferenceChangeListener(this); 235 | } 236 | 237 | 238 | /*private void gotoNotificationAccessSetting() 239 | { 240 | try 241 | { 242 | final Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"); 243 | intent.putExtra("package", getPackageName()); 244 | intent.putExtra("uid", getApplicationInfo().uid); 245 | 246 | startActivity(intent); 247 | } 248 | catch (ActivityNotFoundException e) 249 | { try 250 | { 251 | final Intent intent = new Intent(); 252 | final ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.Settings$NotificationAccessSettingsActivity"); 253 | intent.setComponent(cn); 254 | intent.putExtra(":settings:show_fragment", "NotificationAccessSettings"); 255 | startActivity(intent); 256 | } 257 | catch (Exception ex) 258 | { 259 | return; 260 | } 261 | } 262 | finish(); 263 | } 264 | private boolean notificationListenerEnable() 265 | { 266 | boolean enable = false; 267 | String flat= Settings.Secure.getString(getContentResolver(), "enabled_notification_listeners"); 268 | if ( flat != null ) 269 | { 270 | enable = flat.contains(NotifycationListener.class.getName()); 271 | } 272 | return enable; 273 | } */ 274 | 275 | } 276 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/internal/ImageDraw.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.internal; 2 | import com.moe.LiveVisualizer.draw.*; 3 | import com.moe.LiveVisualizer.draw.circle.*; 4 | import com.moe.LiveVisualizer.draw.line.*; 5 | 6 | import com.moe.LiveVisualizer.service.LiveWallpaper; 7 | import com.moe.LiveVisualizer.inter.Draw; 8 | import com.moe.LiveVisualizer.service.LiveWallpaper.WallpaperEngine; 9 | import android.view.animation.AccelerateInterpolator; 10 | import android.view.animation.CycleInterpolator; 11 | import android.graphics.Shader; 12 | import android.graphics.Matrix; 13 | import android.view.animation.Interpolator; 14 | import android.graphics.LinearGradient; 15 | import android.view.animation.BaseInterpolator; 16 | import android.view.animation.OvershootInterpolator; 17 | import android.view.animation.AccelerateDecelerateInterpolator; 18 | 19 | public class ImageDraw extends BaseInterpolator implements OnColorSizeChangedListener 20 | { 21 | private LiveWallpaper.WallpaperEngine engine; 22 | //private Draw[] drawList=new Draw[13]; 23 | private Shader shader; 24 | private float downSpeed; 25 | private Matrix centerImageMatrix; 26 | private String mode,color_mode; 27 | private WallpaperThread wallpaper; 28 | private Draw draw; 29 | private boolean antialias; 30 | private boolean rotation; 31 | private Interpolator mInterpolator; 32 | public ImageDraw(WallpaperThread wallpaper) 33 | { 34 | this.wallpaper=wallpaper; 35 | this.engine = wallpaper.getEngine(); 36 | color_mode = engine.getPreference().getString("color_mode", "0"); 37 | engine.registerColorSizeChangedListener(this); 38 | setMode(engine.getPreference().getString("visualizer_mode", "0")); 39 | mInterpolator=new AccelerateInterpolator(); 40 | } 41 | 42 | public void setVisualizerRotation(boolean rotation) 43 | { 44 | this.rotation=rotation; 45 | if(draw instanceof CircleDraw) 46 | ((CircleDraw)draw).setVisualizerRotation(rotation); 47 | } 48 | public void setAnitialias(boolean antialias){ 49 | this.antialias=antialias; 50 | if(draw!=null)draw.setAntialias(antialias); 51 | } 52 | @Override 53 | public float getInterpolation(float input){ 54 | //return value*value*getDownSpeed();); 55 | //return mInterpolator.getInterpolation(input); 56 | return (1f- ((1.0f - input) * (1.0f - input)))*getDownSpeed(); 57 | } 58 | public LiveWallpaper.WallpaperEngine getEngine() 59 | { 60 | return engine; 61 | } 62 | public void setMode(String mode) 63 | { 64 | this.mode = mode; 65 | if(draw!=null)draw.finalized(); 66 | draw=null; 67 | } 68 | public WallpaperThread getWallpaperThread() 69 | { 70 | return wallpaper; 71 | } 72 | public void setColorMode(String mode) 73 | { 74 | this.color_mode = mode; 75 | } 76 | public String getColorMode() 77 | { 78 | return color_mode; 79 | } 80 | public void notifySizeChanged() 81 | { 82 | shader = null; 83 | if(draw!=null)draw.notifySizeChanged(); 84 | /*for (Draw draw:drawList) 85 | if (draw != null) 86 | draw.notifySizeChanged();*/ 87 | } 88 | public void setNum(int num){ 89 | if(draw!=null) 90 | draw.setNum(num); 91 | } 92 | public void setDirection(int direction) 93 | { 94 | if(draw instanceof RingDraw) 95 | ((RingDraw)draw).setDirection(direction); 96 | /*for (Draw draw:drawList) 97 | if (draw instanceof RingDraw) 98 | ((RingDraw)draw).setDirection(direction);*/ 99 | } 100 | public void setCircleRadius(int radius) 101 | { 102 | if(draw instanceof RingDraw) 103 | ((RingDraw)draw).setRadius(radius); 104 | /*for (Draw draw:drawList) 105 | if (draw instanceof RingDraw) 106 | ((RingDraw)draw).setRadius(radius);*/ 107 | } 108 | public void setDegressStep(float step) 109 | { 110 | if(draw instanceof RingDraw) 111 | ((RingDraw)draw).setDegressStep(step); 112 | /*for (Draw draw:drawList) 113 | if (draw instanceof RingDraw) 114 | ((RingDraw)draw).setDegressStep(step);*/ 115 | } 116 | public void setOffsetY(int y) 117 | { 118 | if(draw!=null) 119 | draw.setOffsetY(y); 120 | /*for (Draw draw:drawList) 121 | if (draw != null) 122 | draw.setOffsetY(y);*/ 123 | } 124 | 125 | public void setOffsetX(int x) 126 | { 127 | if(draw!=null) 128 | draw.setOffsetX(x); 129 | /*for (Draw draw:drawList) 130 | if (draw != null) 131 | draw.setOffsetX(x);*/ 132 | } 133 | public void setCenterScale(boolean scale) 134 | { 135 | if (scale) 136 | centerImageMatrix = new Matrix(); 137 | else 138 | centerImageMatrix = null; 139 | } 140 | public Matrix getCenterScale() 141 | { 142 | return centerImageMatrix; 143 | } 144 | public void setCutImage(boolean cut) 145 | { 146 | if(draw instanceof RingDraw) 147 | ((RingDraw)draw).setCutImage(cut); 148 | /*for (Draw draw:drawList) 149 | if (draw instanceof RingDraw) 150 | ((RingDraw)draw).setCutImage(cut);*/ 151 | 152 | } 153 | 154 | public void setRound(boolean round) 155 | { 156 | if(draw!=null) 157 | draw.setRound(round); 158 | /*for (Draw draw:drawList) 159 | if (draw != null) 160 | draw.setRound(round);*/ 161 | } 162 | 163 | public void setDownSpeed(int speed) 164 | { 165 | downSpeed =speed/50f; 166 | } 167 | private float getDownSpeed() 168 | { 169 | return downSpeed; 170 | } 171 | public void setDrawHeight(float height) 172 | { 173 | if(draw!=null) 174 | draw.onDrawHeightChanged(height); 175 | /*for (Draw draw:drawList) 176 | if (draw != null) 177 | draw.onDrawHeightChanged(height);*/ 178 | } 179 | public void setBorderHeight(int height) 180 | { 181 | if(draw!=null) 182 | draw.onBorderHeightChanged(height); 183 | /*for (Draw draw:drawList) 184 | if (draw != null) 185 | draw.onBorderHeightChanged(height);*/ 186 | } 187 | public void setSpaceWidth(int space) 188 | { 189 | if(draw!=null) 190 | draw.onSpaceWidthChanged(space); 191 | /*for (Draw draw:drawList) 192 | if (draw != null) 193 | draw.onSpaceWidthChanged(space);*/ 194 | } 195 | public void setBorderWidth(int width) 196 | { 197 | if(draw!=null) 198 | draw.onBorderWidthChanged(width); 199 | /*for (Draw draw:drawList) 200 | if (draw != null) 201 | draw.onBorderWidthChanged(width);*/ 202 | } 203 | @Override 204 | public void onColorSizeChanged() 205 | { 206 | shader = null; 207 | } 208 | public byte[] getWave() 209 | { 210 | 211 | return wallpaper.getWave(); 212 | } 213 | public double[] getFft() 214 | { 215 | return wallpaper.getFft(); 216 | } 217 | 218 | final public Draw lockData() 219 | { 220 | if(draw==null){ 221 | get(); 222 | if(draw!=null){ 223 | draw.setAntialias(antialias); 224 | } 225 | if(draw instanceof CircleDraw) 226 | ((CircleDraw)draw).setVisualizerRotation(rotation); 227 | } 228 | return draw; 229 | 230 | } 231 | 232 | private Draw get() 233 | { 234 | switch (mode) 235 | { 236 | case "0"://柱形图 237 | return draw=new RadialDraw(this); 238 | case "1"://折线图 239 | return draw= new LineChartDraw(this); 240 | case "2"://圆形射线 241 | return draw = new CircleRadialDraw(this); 242 | case "3"://弹弹圈 243 | return draw = new PopCircleDraw(this); 244 | case "4"://圆环三角 245 | return draw = new CircleTriangleDraw(this); 246 | case "5"://射线 247 | return draw = new CenterRadialDraw(this); 248 | case "6"://波纹 249 | return draw = new RippleDraw(this); 250 | case "7"://离散 251 | return draw = new CircleDisperseDraw(this); 252 | case "8"://山坡线 253 | return draw = new YamaLineDraw(this); 254 | case "9"://方块 255 | return draw = new SquareDraw(this); 256 | case "10"://打砖块 257 | return draw = new BlockBreakerDraw(this); 258 | case "11": 259 | return draw = new UnKnow1(this); 260 | case "12": 261 | return draw = new UnKnow2(this); 262 | case "13": 263 | return draw=new UnKnow3(this); 264 | case "14"://心形 265 | return draw=new HeartDraw(this); 266 | } 267 | return null; 268 | /*switch (mode) 269 | { 270 | case "0"://柱形图 271 | return drawList[0] == null ?drawList[0] = new RadialDraw(this): drawList[0]; 272 | case "1"://折线图 273 | return drawList[1] == null ?drawList[1] = new LineChartDraw(this): drawList[1]; 274 | case "2"://圆形射线 275 | return drawList[2] == null ?drawList[2] = new CircleRadialDraw(this): drawList[2]; 276 | case "3"://弹弹圈 277 | return drawList[3] == null ?drawList[3] = new PopCircleDraw(this): drawList[3]; 278 | case "4"://圆环三角 279 | return drawList[4] == null ?drawList[4] = new CircleTriangleDraw(this): drawList[4]; 280 | case "5"://射线 281 | return drawList[5] == null ?drawList[5] = new CenterRadialDraw(this): drawList[5]; 282 | case "6"://波纹 283 | return drawList[6] == null ?drawList[6] = new RippleDraw(this): drawList[6]; 284 | case "7"://离散 285 | return drawList[7] == null ?drawList[7] = new CircleDisperseDraw(this): drawList[7]; 286 | case "8"://山坡线 287 | return drawList[8] == null ?drawList[8] = new YamaLineDraw(this): drawList[8]; 288 | case "9"://方块 289 | return drawList[9] == null ?drawList[9] = new SquareDraw(this): drawList[9]; 290 | case "10"://打砖块 291 | return drawList[10] == null ?drawList[10] = new BlockBreakerDraw(this): drawList[10]; 292 | case "11": 293 | return drawList[11] == null ?drawList[11] = new UnKnow1(this): drawList[11]; 294 | case "12": 295 | return drawList[12] == null ?drawList[12] = new UnKnow2(this): drawList[12]; 296 | } 297 | return null;*/ 298 | } 299 | public void resetShader() 300 | { 301 | this.shader = null; 302 | } 303 | public synchronized Shader getShader() 304 | { 305 | if (shader == null) 306 | { 307 | switch (engine.getPreference().getString("color_direction", "0")) 308 | { 309 | case "0"://lefttoright 310 | shader = new LinearGradient(0, 0, engine.getDisplayWidth(), 0, engine.getColorList().toArray(), null, LinearGradient.TileMode.CLAMP); 311 | break;//righttoleft 312 | case "1": 313 | shader = new LinearGradient(engine.getDisplayWidth(), 0, 0, 0, engine.getColorList().toArray(), null, LinearGradient.TileMode.CLAMP); 314 | 315 | break;//toptobottom 316 | case "2":shader = new LinearGradient(0, 0, 0, engine.getDisplayHeight(), engine.getColorList().toArray(), null, LinearGradient.TileMode.CLAMP); 317 | 318 | break;//bottomtotop 319 | case "3":shader = new LinearGradient(0, engine.getDisplayHeight(), 0, 0, engine.getColorList().toArray(), null, LinearGradient.TileMode.CLAMP); 320 | 321 | break;//toplefttobottomright 322 | case "4":shader = new LinearGradient(0, 0, engine.getDisplayWidth(), engine.getDisplayHeight(), engine.getColorList().toArray(), null, LinearGradient.TileMode.CLAMP); 323 | 324 | break;//toprighttobottomleft 325 | case "5":shader = new LinearGradient(engine.getDisplayWidth(), 0, 0, engine.getDisplayHeight(), engine.getColorList().toArray(), null, LinearGradient.TileMode.CLAMP); 326 | 327 | break;//bottomlefttotopright 328 | case "6":shader = new LinearGradient(0, engine.getDisplayHeight(), engine.getDisplayWidth(), 0, engine.getColorList().toArray(), null, LinearGradient.TileMode.CLAMP); 329 | 330 | break;//bottomrighttotopright 331 | case "7":shader = new LinearGradient(engine.getDisplayWidth(), engine.getDisplayHeight(), 0, 0, engine.getColorList().toArray(), null, LinearGradient.TileMode.CLAMP); 332 | 333 | break; 334 | } 335 | } 336 | return shader; 337 | } 338 | } 339 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/fragment/CircleSettingFragment.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.fragment; 2 | import android.preference.PreferenceActivity; 3 | import android.os.PersistableBundle; 4 | import android.os.Bundle; 5 | import android.preference.PreferenceFragment; 6 | import android.preference.Preference; 7 | import android.app.ProgressDialog; 8 | import android.app.AlertDialog; 9 | import java.lang.ref.SoftReference; 10 | import android.net.Uri; 11 | import java.io.File; 12 | import android.content.DialogInterface; 13 | import android.content.Intent; 14 | import android.app.Activity; 15 | import java.lang.reflect.Field; 16 | import android.widget.ProgressBar; 17 | import java.io.FileOutputStream; 18 | import java.io.InputStream; 19 | import android.os.Build; 20 | import android.widget.Toast; 21 | import java.io.IOException; 22 | import android.os.Handler; 23 | import android.os.Message; 24 | import android.app.Dialog; 25 | import android.graphics.Bitmap; 26 | import android.util.DisplayMetrics; 27 | import android.view.WindowManager; 28 | import android.app.Service; 29 | import com.moe.LiveVisualizer.preference.SeekBarPreference; 30 | import com.moe.LiveVisualizer.R; 31 | import com.moe.LiveVisualizer.activity.CropActivity; 32 | 33 | public class CircleSettingFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener 34 | { 35 | private DisplayMetrics display; 36 | 37 | private final static int CIRCLE=0x03; 38 | 39 | private final static int CIRCLE_SUCCESS=0x06; 40 | private final static int CIRCLE_DISMISS=0x07; 41 | private ProgressDialog circle_dialog; 42 | private AlertDialog circle_delete; 43 | private SoftReference weak; 44 | @Override 45 | public void onActivityCreated(Bundle savedInstanceState) 46 | { 47 | // TODO: Implement this method 48 | super.onActivityCreated(savedInstanceState); 49 | display =new DisplayMetrics(); 50 | ( (WindowManager)getActivity().getSystemService(Service.WINDOW_SERVICE)).getDefaultDisplay().getRealMetrics(display); 51 | 52 | getPreferenceManager().setSharedPreferencesName("moe"); 53 | addPreferencesFromResource(R.xml.circle_setting); 54 | findPreference("circle_image").setOnPreferenceClickListener(this); 55 | int width=Math.min(display.widthPixels,display.heightPixels); 56 | int height=Math.max(display.widthPixels,display.heightPixels); 57 | SeekBarPreference offsetX=(SeekBarPreference)findPreference("offsetX"); 58 | offsetX.setMax(width); 59 | offsetX.setDefaultValue(width/2); 60 | SeekBarPreference offsetY=(SeekBarPreference) findPreference("offsetY"); 61 | offsetY.setMax(height); 62 | offsetY.setDefaultValue(height/2); 63 | SeekBarPreference circle_radius=(SeekBarPreference) findPreference("circleRadius"); 64 | circle_radius.setMax(width); 65 | circle_radius.setDefaultValue(width/3); 66 | } 67 | 68 | @Override 69 | public boolean onPreferenceClick(Preference p1) 70 | { 71 | switch(p1.getKey()){ 72 | case "circle_image": 73 | final File circle=new File(getActivity().getExternalFilesDir(null), "circle"); 74 | if ( circle.exists() ) 75 | { 76 | if ( circle_delete == null ) 77 | { 78 | circle_delete = new AlertDialog.Builder(getActivity()).setTitle("确认").setMessage("是否清除当前图片?").setPositiveButton("取消", null).setNegativeButton("确定", new DialogInterface.OnClickListener(){ 79 | 80 | @Override 81 | public void onClick(DialogInterface p1, int p2) 82 | { 83 | circle.delete(); 84 | getActivity().sendBroadcast(new Intent("circle_changed")); 85 | 86 | } 87 | }).create(); 88 | } 89 | circle_delete.show(); 90 | } 91 | else 92 | { 93 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 94 | intent.setType("image/*"); 95 | /*intent.putExtra("crop", "true"); 96 | //width:height 97 | intent.putExtra("aspectX", 1); 98 | intent.putExtra("aspectY", 1); 99 | intent.putExtra("outputX", display.widthPixels / 3); 100 | intent.putExtra("outputY", display.widthPixels / 3); 101 | intent.putExtra("output", Uri.fromFile(circle)); 102 | intent.putExtra("return-data", false); 103 | intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());*/ 104 | try 105 | {startActivityForResult(Intent.createChooser(intent, "Choose Image"), CIRCLE);} 106 | catch (Exception e) 107 | {} 108 | } 109 | break; 110 | } 111 | return false; 112 | } 113 | @Override 114 | public void onActivityResult(int requestCode, int resultCode, final Intent data) 115 | { 116 | if ( resultCode == Activity.RESULT_OK ) 117 | switch ( requestCode ) 118 | { 119 | case CIRCLE: 120 | if(data.getData()==null)break; 121 | weak=new SoftReference(data.getData()); 122 | if ( circle_dialog == null ) 123 | { 124 | circle_dialog = new ProgressDialog(getActivity()); 125 | circle_dialog.setMessage("如何处理图片"); 126 | circle_dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 127 | circle_dialog.setButton(ProgressDialog.BUTTON1,"裁剪", new DialogInterface.OnClickListener(){ 128 | 129 | @Override 130 | public void onClick(DialogInterface p1, int p2) 131 | { 132 | try{ 133 | Field progressBar=circle_dialog.getClass().getDeclaredField("mProgress"); 134 | progressBar.setAccessible(true); 135 | ((ProgressBar)progressBar.get(circle_dialog)).setVisibility(ProgressBar.VISIBLE); 136 | }catch(Exception e){} 137 | new Thread(){ 138 | public void run() 139 | { 140 | final File tmp=new File(getActivity().getExternalFilesDir(null), "tmpImage"); 141 | FileOutputStream fos=null; 142 | InputStream is=null; 143 | try 144 | { 145 | fos = new FileOutputStream(tmp); 146 | is = getActivity().getContentResolver().openInputStream(weak.get()); 147 | byte[] buffer=new byte[16*1024]; 148 | int len; 149 | while ( (len = is.read(buffer)) != -1 ) 150 | fos.write(buffer, 0, len); 151 | fos.flush(); 152 | final File circle_file=new File(getActivity().getExternalFilesDir(null), "circle"); 153 | Intent intent = new Intent("com.android.camera.action.CROP"); 154 | intent.setClass(getActivity(),CropActivity.class); 155 | /*if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ) 156 | { 157 | intent.setDataAndType(FileProvider.getUriForFile(getActivity(), getActivity().getPackageName() + ".provider", tmp), "image/*"); 158 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 159 | } 160 | else*/ 161 | intent.setDataAndType(Uri.fromFile(tmp), "image/*"); 162 | 163 | intent.putExtra("crop", "true"); 164 | intent.putExtra("aspectX", 1); 165 | intent.putExtra("aspectY", 1); 166 | int width=Math.min(display.widthPixels,display.heightPixels)/3; 167 | intent.putExtra("outputX", width); 168 | intent.putExtra("outputY", width); 169 | intent.putExtra("output", Uri.fromFile(circle_file)); 170 | intent.putExtra("return-data", false); 171 | intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString()); 172 | try 173 | { 174 | startActivityForResult(intent, CIRCLE_SUCCESS); 175 | } 176 | catch (Exception e) 177 | {Toast.makeText(getActivity(),"请安装一个裁剪图片的软件",Toast.LENGTH_LONG).show();} 178 | 179 | } 180 | catch (Exception e) 181 | {} 182 | finally 183 | { 184 | try 185 | { 186 | if ( fos != null )fos.close(); 187 | } 188 | catch (IOException e) 189 | {} 190 | try 191 | { 192 | if ( is != null )is.close(); 193 | } 194 | catch (IOException e) 195 | {} 196 | } 197 | handler.obtainMessage(CIRCLE_DISMISS).sendToTarget(); 198 | } 199 | }.start(); 200 | } 201 | }); 202 | circle_dialog.setButton(ProgressDialog.BUTTON2,"原图", new DialogInterface.OnClickListener(){ 203 | 204 | @Override 205 | public void onClick(DialogInterface p1, int p2) 206 | { 207 | try{ 208 | Field progressBar=circle_dialog.getClass().getDeclaredField("mProgress"); 209 | progressBar.setAccessible(true); 210 | ((ProgressBar)progressBar.get(circle_dialog)).setVisibility(ProgressBar.VISIBLE); 211 | }catch(Exception e){} 212 | new Thread(){ 213 | public void run(){ 214 | final File tmp=new File(getActivity().getExternalFilesDir(null), "circle"); 215 | FileOutputStream fos=null; 216 | InputStream is=null; 217 | try 218 | { 219 | fos = new FileOutputStream(tmp); 220 | is = getActivity().getContentResolver().openInputStream(weak.get()); 221 | byte[] buffer=new byte[16*1024]; 222 | int len; 223 | while ( (len = is.read(buffer)) != -1 ) 224 | fos.write(buffer, 0, len); 225 | fos.flush(); 226 | } 227 | catch (Exception e) 228 | {} 229 | finally 230 | { 231 | try 232 | { 233 | if ( fos != null )fos.close(); 234 | } 235 | catch (IOException e) 236 | {} 237 | try 238 | { 239 | if ( is != null )is.close(); 240 | } 241 | catch (IOException e) 242 | {} 243 | } 244 | getActivity().sendBroadcast(new Intent("circle_changed")); 245 | handler.obtainMessage(CIRCLE_DISMISS).sendToTarget(); 246 | } 247 | }.start(); 248 | } 249 | }); 250 | circle_dialog.setButton(ProgressDialog.BUTTON3,"取消",handler.obtainMessage(CIRCLE_DISMISS)); 251 | circle_dialog.setCanceledOnTouchOutside(false); 252 | } 253 | circle_dialog.show(); 254 | try 255 | { 256 | Field progressBar=circle_dialog.getClass().getDeclaredField("mProgress"); 257 | progressBar.setAccessible(true); 258 | ((ProgressBar)progressBar.get(circle_dialog)).setVisibility(ProgressBar.GONE); 259 | Field show=Dialog.class.getDeclaredField("mShowing"); 260 | show.setAccessible(true); 261 | show.setBoolean(circle_dialog,false); 262 | } 263 | catch (Exception e) 264 | {} 265 | break; 266 | case CIRCLE_SUCCESS: 267 | getActivity().sendBroadcast(new Intent("circle_changed")); 268 | break; 269 | } 270 | } 271 | private Handler handler=new Handler(){ 272 | 273 | @Override 274 | public void handleMessage(Message msg) 275 | { 276 | switch(msg.what){ 277 | case CIRCLE_DISMISS: 278 | if(circle_dialog!=null){ 279 | try{ 280 | Field show=Dialog.class.getDeclaredField("mShowing"); 281 | show.setAccessible(true); 282 | show.setBoolean(circle_dialog,true); 283 | }catch(Exception e){} 284 | circle_dialog.dismiss(); 285 | } 286 | break; 287 | } 288 | } 289 | 290 | }; 291 | } 292 | -------------------------------------------------------------------------------- /app/src/main/java/com/moe/LiveVisualizer/activity/ColorListActivity.java: -------------------------------------------------------------------------------- 1 | package com.moe.LiveVisualizer.activity; 2 | import android.app.Activity; 3 | import android.os.Bundle; 4 | import android.view.Menu; 5 | import android.view.MenuItem; 6 | import android.app.AlertDialog; 7 | import com.moe.LiveVisualizer.widget.ColorPickerView; 8 | import android.content.SharedPreferences; 9 | import java.io.OutputStream; 10 | import android.os.Handler; 11 | import android.os.Message; 12 | import java.io.File; 13 | import java.io.BufferedReader; 14 | import java.io.InputStreamReader; 15 | import java.io.FileInputStream; 16 | import java.io.FileNotFoundException; 17 | import java.io.FileOutputStream; 18 | import java.io.IOException; 19 | import com.moe.LiveVisualizer.utils.ColorList; 20 | import android.widget.ListView; 21 | import com.moe.LiveVisualizer.adapter.ColorAdapter; 22 | import android.view.View; 23 | import android.widget.AdapterView; 24 | import android.widget.Adapter; 25 | import android.widget.PopupWindow; 26 | import android.widget.LinearLayout; 27 | import android.widget.TextView; 28 | import android.view.Gravity; 29 | import android.graphics.drawable.BitmapDrawable; 30 | import com.moe.LiveVisualizer.internal.ShadowDrawable; 31 | import android.view.ContextThemeWrapper; 32 | import com.moe.LiveVisualizer.widget.PopupLayout; 33 | import android.content.Intent; 34 | import android.widget.EditText; 35 | import android.content.DialogInterface; 36 | import android.graphics.Color; 37 | import com.moe.LiveVisualizer.app.ColorDialog; 38 | import android.widget.*; 39 | import android.net.*; 40 | 41 | public class ColorListActivity extends Activity implements ColorPickerView.OnColorCheckedListener,ListView.OnItemClickListener,View.OnClickListener 42 | { 43 | private ColorList colorList; 44 | private static final int INPUT=0; 45 | private AlertDialog colorPicker; 46 | private ListView listview; 47 | private Object fileLock=new Object(); 48 | private PopupWindow popup; 49 | @Override 50 | protected void onCreate(Bundle savedInstanceState) 51 | { 52 | super.onCreate(savedInstanceState); 53 | colorList=new ColorList(); 54 | listview=new ListView(this); 55 | listview.setAdapter(new ColorAdapter(colorList)); 56 | listview.setOnItemClickListener(this); 57 | listview.setFitsSystemWindows(true); 58 | setContentView(listview); 59 | setTitle("色彩组"); 60 | getActionBar().setDisplayHomeAsUpEnabled(true); 61 | getActionBar().setHomeButtonEnabled(true); 62 | read(); 63 | } 64 | 65 | @Override 66 | public boolean onCreateOptionsMenu(Menu menu) 67 | { 68 | MenuItem item=menu.add(0,0,0,"手动输入"); 69 | item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); 70 | item=menu.add(1,1,1,"调色板"); 71 | menu.add(2,2,2,"导入"); 72 | menu.add(3,3,3,"导出"); 73 | menu.add(4,4,4,"清空"); 74 | //VectorDrawableCompat plus=VectorDrawableCompat.create(getResources(),R.drawable.plus,getTheme()); 75 | //plus.setTint(0xffffffff); 76 | //item.setIcon(plus); 77 | item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); 78 | return true; 79 | } 80 | @Override 81 | public boolean onOptionsItemSelected(MenuItem item) 82 | { 83 | switch(item.getItemId()){ 84 | case android.R.id.home: 85 | finish(); 86 | return true; 87 | case 0: 88 | if(colorPicker==null){ 89 | final EditText view=new EditText(this); 90 | // view.setOnColorCheckedListener(this); 91 | colorPicker = new AlertDialog.Builder(this).setTitle("输入十六进制颜色").setView(view).setPositiveButton("取消", null).setNegativeButton("确定", new DialogInterface.OnClickListener(){ 92 | 93 | @Override 94 | public void onClick(DialogInterface p1, int p2) 95 | { 96 | try{ 97 | colorList.add( Color.parseColor(view.getText().toString())); 98 | ((ColorAdapter)listview.getAdapter()).notifyDataSetChanged(); 99 | notifyColorFileChanged(); 100 | }catch(Exception e){} 101 | } 102 | }).create(); 103 | } 104 | colorPicker.show(); 105 | break; 106 | case 1: 107 | 108 | ColorDialog cd=(ColorDialog) getFragmentManager().findFragmentByTag("color"); 109 | if(cd==null){cd=new ColorDialog(); 110 | cd.setOnColorCheckedListener(this);} 111 | if(cd.isAdded())getFragmentManager().beginTransaction().show(cd).commit(); 112 | else cd.show(getFragmentManager(),"color"); 113 | break; 114 | case 2: 115 | Intent intent=new Intent(Intent.ACTION_GET_CONTENT); 116 | intent.setType("*/*"); 117 | startActivityForResult(intent,2534); 118 | break; 119 | case 3: 120 | if(colorList.isEmpty()){ 121 | Toast.makeText(this,"没有数据",Toast.LENGTH_SHORT).show(); 122 | }else{ 123 | final File backup=getExternalFilesDir("backup"); 124 | if(!backup.exists()) 125 | backup.mkdirs(); 126 | final EditText filename=new EditText(this); 127 | new AlertDialog.Builder(this).setTitle("文件命名").setView(filename).setPositiveButton("保存", new DialogInterface.OnClickListener(){ 128 | 129 | @Override 130 | public void onClick(DialogInterface p1, int p2) 131 | { 132 | final File file=new File(backup,filename.getText().toString().trim().concat(".mcl")); 133 | if(file.exists()){ 134 | Toast.makeText(ColorListActivity.this,"文件已存在",Toast.LENGTH_SHORT).show(); 135 | return; 136 | } 137 | new Thread(){ 138 | public void run(){ 139 | save(file); 140 | runOnUiThread(new Runnable(){ 141 | 142 | @Override 143 | public void run() 144 | { 145 | Toast.makeText(ColorListActivity.this,"保存成功\n".concat(backup.getAbsolutePath()),Toast.LENGTH_SHORT).show(); 146 | } 147 | }); 148 | } 149 | }.start(); 150 | } 151 | }).setNegativeButton(android.R.string.cancel, null).show(); 152 | } 153 | break; 154 | case 4: 155 | colorList.clear(); 156 | ((ColorAdapter)listview.getAdapter()).notifyDataSetChanged(); 157 | notifyColorFileChanged(); 158 | break; 159 | } 160 | return super.onOptionsItemSelected(item); 161 | } 162 | 163 | @Override 164 | public void onColorChecked(int color) 165 | { 166 | colorList.add(color); 167 | ((ColorAdapter)listview.getAdapter()).notifyDataSetChanged(); 168 | notifyColorFileChanged(); 169 | //colorPicker.dismiss(); 170 | ColorDialog cd=(ColorDialog) getFragmentManager().findFragmentByTag("color"); 171 | if(cd!=null)cd.dismiss(); 172 | } 173 | 174 | @Override 175 | public void onItemClick(AdapterView p1, View p2, int p3, long p4) 176 | { 177 | if(popup==null){ 178 | PopupLayout group=new PopupLayout(this); 179 | group.addView(new View(this),new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,p2.getHeight())); 180 | TextView remove=new TextView(this); 181 | remove.setText("移除"); 182 | remove.setOnClickListener(this); 183 | remove.setGravity(Gravity.CENTER_VERTICAL); 184 | group.addView(remove,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,p2.getHeight())); 185 | popup=new PopupWindow(p2.getContext()); 186 | popup.setContentView(group); 187 | popup.setWidth(p2.getHeight()*2); 188 | popup.setHeight(p2.getHeight()*2); 189 | popup.setBackgroundDrawable(new ShadowDrawable()); 190 | popup.setTouchable(true); 191 | popup.setOutsideTouchable(true); 192 | remove.setId(popup.hashCode()); 193 | } 194 | ((PopupLayout)popup.getContentView()).getChildAt(0).setBackgroundColor(colorList.get(p3)); 195 | popup.showAsDropDown(p2,(p2.getWidth()-p2.getHeight())/2,-(int)(p2.getHeight()/2.0f)); 196 | popup.getContentView().setId(p3); 197 | } 198 | 199 | 200 | /*private Handler handler=new Handler(){ 201 | 202 | @Override 203 | public void handleMessage(Message msg) 204 | { 205 | switch(msg.what){ 206 | case INPUT: 207 | break; 208 | } 209 | } 210 | 211 | };*/ 212 | private void notifyColorFileChanged(){ 213 | new Thread(){ 214 | public void run(){ 215 | synchronized(fileLock){ 216 | File colorFile=new File(getExternalFilesDir(null),"color"); 217 | save(colorFile); 218 | } 219 | sendBroadcast(new Intent("color_changed")); 220 | }}.start(); 221 | } 222 | private void save(File file){ 223 | OutputStream os=null; 224 | try 225 | { 226 | os = new FileOutputStream(file); 227 | for(int i=0;i