├── README.md
├── app
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── gplibs
│ │ └── magic_surface_view_sample
│ │ ├── App.java
│ │ ├── LightSampleActivity.java
│ │ ├── MacWindowAnimActivity.java
│ │ ├── MainActivity.java
│ │ ├── MatrixAnimSampleActivity.java
│ │ ├── MultiScrapAnimActivity.java
│ │ ├── MultiSlideAnimActivity.java
│ │ ├── VortexAnimActivity.java
│ │ ├── WaveAnimActivity.java
│ │ ├── common
│ │ ├── AnimHelper.java
│ │ ├── Direction.java
│ │ ├── FloatValueAnimator.java
│ │ ├── MagicActivity.java
│ │ └── RandomNumber.java
│ │ ├── launch
│ │ ├── LaunchActivity.java
│ │ ├── LaunchBackgroundUpdater.java
│ │ ├── LaunchButtonMatrixUpdater.java
│ │ ├── LaunchButtonModelUpdater.java
│ │ ├── LaunchSceneUpdater.java
│ │ └── LaunchTextModelUpdater.java
│ │ └── updater
│ │ ├── MacWindowAnimUpdater.java
│ │ ├── MultiScrapUpdater.java
│ │ ├── MultiSlideUpdater.java
│ │ ├── VortexAnimUpdater.java
│ │ └── WaveAnimUpdater.java
│ └── res
│ ├── drawable
│ ├── btn_bg.xml
│ ├── dark_bg.xml
│ └── surface_bg.xml
│ ├── layout
│ ├── activity_launch.xml
│ ├── activity_light_sample.xml
│ ├── activity_mac_window_anim.xml
│ ├── activity_magic.xml
│ ├── activity_main.xml
│ ├── activity_matrix_anim_sample.xml
│ ├── activity_multi_fold_anim.xml
│ ├── activity_multi_scrap_anim.xml
│ ├── activity_multi_slide_anim.xml
│ ├── activity_vortex_anim.xml
│ ├── activity_wave_anim.xml
│ └── item_activity.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── values-v19
│ └── styles.xml
│ ├── values-v21
│ └── styles.xml
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle
/README.md:
--------------------------------------------------------------------------------
1 | # android-magic-surface-view-sample
2 |
3 | 这是基于MagicSurfaceView库的示例项目 ([下载此示例项目apk](https://github.com/gplibs/resources/raw/master/android/magic-surface-view/apk/magic-surface-view-sample-release.apk))。
4 | MagicSurfaceView库地址:
5 |
6 | 此项目只有几个简陋的示例,只为抛砖引玉。
7 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | Properties properties = new Properties()
4 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
5 |
6 | android {
7 | compileSdkVersion 25
8 | buildToolsVersion "25.0.2"
9 |
10 | defaultConfig {
11 | applicationId "com.gplibs.magic_surface_view_sample"
12 | minSdkVersion 11
13 | targetSdkVersion 25
14 | versionCode 111
15 | versionName "1.1.1"
16 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
17 | }
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | }
25 |
26 | dependencies {
27 | compile fileTree(dir: 'libs', include: ['*.jar'])
28 | compile 'com.gplibs:magic-surface-view:1.1.1'
29 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
30 | exclude group: 'com.android.support', module: 'support-annotations'
31 | })
32 | compile 'com.android.support:appcompat-v7:25.3.1'
33 | compile 'com.android.support.constraint:constraint-layout:1.0.1'
34 | testCompile 'junit:junit:4.12'
35 | }
36 |
--------------------------------------------------------------------------------
/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 /Users/guoping/Software/dev/IDEA/android-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 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/App.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample;
2 |
3 | import android.app.Application;
4 |
5 | public class App extends Application {
6 |
7 | @Override
8 | public void onCreate() {
9 | super.onCreate();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/LightSampleActivity.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.IdRes;
5 | import android.view.MotionEvent;
6 | import android.view.View;
7 | import android.widget.CompoundButton;
8 | import android.widget.RadioGroup;
9 | import android.widget.SeekBar;
10 | import android.widget.TextView;
11 | import android.widget.ToggleButton;
12 |
13 | import com.gplibs.magic_surface_view_sample.common.MagicActivity;
14 | import com.gplibs.magicsurfaceview.MagicScene;
15 | import com.gplibs.magicsurfaceview.MagicSceneBuilder;
16 | import com.gplibs.magicsurfaceview.MagicSurface;
17 | import com.gplibs.magicsurfaceview.MagicSurfaceView;
18 | import com.gplibs.magicsurfaceview.PointLight;
19 | import com.gplibs.magicsurfaceview.ReusableVec;
20 | import com.gplibs.magicsurfaceview.Vec;
21 | import com.gplibs.magicsurfaceview.VecPool;
22 |
23 | public class LightSampleActivity extends MagicActivity {
24 |
25 | private View mViewContainer;
26 | private MagicSurfaceView mSurfaceView;
27 | private TextView mTvContent;
28 |
29 | private TextView mTvPos;
30 | private TextView mTvShininess;
31 | private SeekBar mSbZ;
32 | private SeekBar mSbShininess;
33 | private RadioGroup mRadioGroup;
34 | private ToggleButton mToggleButton;
35 |
36 | private MagicScene mScene; // 场景对象
37 | private MagicSurface mSurface; // 渲染对象
38 | private PointLight mPointLight; // 点光源对象
39 | private Vec mLightPos = new Vec(3); // 光源位置
40 |
41 | private boolean mIsFirstResume = true;
42 | private float mX, mY;
43 |
44 | @Override
45 | protected void onCreate(Bundle savedInstanceState) {
46 | super.onCreate(savedInstanceState);
47 | setContentView(R.layout.activity_light_sample);
48 | setTitle("LightSample");
49 |
50 | initViews();
51 | }
52 |
53 | private void initViews() {
54 | mSurfaceView = (MagicSurfaceView) findViewById(R.id.surface_view);
55 | mTvContent = (TextView) findViewById(R.id.tv_content);
56 |
57 | mViewContainer = findViewById(R.id.view_container);
58 | mViewContainer.setOnTouchListener(new View.OnTouchListener() {
59 | @Override
60 | public boolean onTouch(View v, MotionEvent event) {
61 | moveLight(event.getX(), event.getY());
62 | return true;
63 | }
64 | });
65 |
66 | mTvPos = (TextView) findViewById(R.id.tv_pos);
67 | mTvShininess = (TextView) findViewById(R.id.tv_shininess);
68 |
69 | mSbZ = (SeekBar) findViewById(R.id.sb_z);
70 | mSbShininess = (SeekBar) findViewById(R.id.sb_shininess);
71 | SeekBar.OnSeekBarChangeListener onSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
72 | @Override
73 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
74 | if (seekBar == mSbZ) {
75 | moveLightZ(0.2f + 0.8f * progress / 100.f);
76 | mTvPos.setText("z:" + mLightPos.z());
77 | } else {
78 | mSurface.setShininess(progress);
79 | mTvShininess.setText("shininess:" + progress);
80 | }
81 | }
82 |
83 | @Override
84 | public void onStartTrackingTouch(SeekBar seekBar) {
85 |
86 | }
87 |
88 | @Override
89 | public void onStopTrackingTouch(SeekBar seekBar) {
90 |
91 | }
92 | };
93 | mSbZ.setOnSeekBarChangeListener(onSeekBarChangeListener);
94 | mSbShininess.setOnSeekBarChangeListener(onSeekBarChangeListener);
95 |
96 | mRadioGroup = (RadioGroup) findViewById(R.id.radio_group);
97 | mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
98 | @Override
99 | public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
100 | int color;
101 | switch (checkedId) {
102 | case R.id.rb_red:
103 | color = 0XFF800000;
104 | break;
105 | case R.id.rb_green:
106 | color = 0XFF008000;
107 | break;
108 | case R.id.rb_blue:
109 | color = 0XFF000080;
110 | break;
111 | default:
112 | color = 0XFF808080;
113 | break;
114 | }
115 | updateColor(color);
116 | }
117 | });
118 |
119 | mToggleButton = (ToggleButton) findViewById(R.id.toggle_button);
120 | mToggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
121 | @Override
122 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
123 | mPointLight.setEnable(isChecked);
124 | }
125 | });
126 | }
127 |
128 | private void render() {
129 | // 光源默认位置 (0.f, 0.f, 0.2f): MagicSurfaceView 正中, Z轴向屏幕外0.2
130 | mLightPos.setXYZ(mX, mY, 0.2f + 0.8f * mSbZ.getProgress() / 100.f);
131 | mPointLight = new PointLight(0XFF808080, mLightPos);
132 | mSurface = new MagicSurface(mTvContent);
133 | mSurface.setShininess(mSbShininess.getProgress());
134 | mSurface.setGrid(50, 50);
135 | mScene = new MagicSceneBuilder(mSurfaceView)
136 | .addSurfaces(mSurface)
137 | .ambientColor(0XFF333333) // 环境光,设置暗些灯光效果才明显
138 | .addLights(mPointLight)
139 | .build();
140 | mSurfaceView.render(mScene);
141 | }
142 |
143 | public void moveLight(float x, float y) {
144 | ReusableVec sceneTopLeft = VecPool.get(3);
145 | mScene.getPosition(0, 0, sceneTopLeft);
146 | mX = sceneTopLeft.x() + mScene.getWidth() * x / mViewContainer.getWidth();
147 | mY = sceneTopLeft.y() - mScene.getHeight() * y / mViewContainer.getHeight(); // 场景Y轴向上所以要减
148 | sceneTopLeft.free();
149 | mLightPos.setXY(mX, mY);
150 | updatePosition();
151 | }
152 |
153 | // 修改灯光位置Z坐标
154 | private void moveLightZ(float z) {
155 | mLightPos.z(z);
156 | updatePosition();
157 | }
158 |
159 | // 修改灯光颜色
160 | private void updateColor(int color) {
161 | mPointLight.setColor(color);
162 | }
163 |
164 | // 修改灯光水平位置
165 | private void updatePosition() {
166 | mPointLight.setPosition(mLightPos);
167 | }
168 |
169 | @Override
170 | protected void onPageAnimEnd() {
171 | render();
172 | }
173 |
174 | @Override
175 | protected void onPause() {
176 | super.onPause();
177 | mSurfaceView.onPause();
178 | }
179 |
180 | @Override
181 | protected void onResume() {
182 | super.onResume();
183 | getWindow().getDecorView().post(new Runnable() {
184 | @Override
185 | public void run() {
186 | if (!mIsFirstResume) {
187 | render();
188 | } else {
189 | mIsFirstResume = false;
190 | }
191 | mSurfaceView.onResume();
192 | }
193 | });
194 | }
195 |
196 | @Override
197 | protected void onDestroy() {
198 | super.onDestroy();
199 | // 释放资源
200 | mSurfaceView.onDestroy();
201 | }
202 |
203 | @Override
204 | public void onBackPressed() {
205 | mSurfaceView.setVisibility(View.INVISIBLE);
206 | mViewContainer.postDelayed(new Runnable() {
207 | @Override
208 | public void run() {
209 | LightSampleActivity.super.onBackPressed();
210 | }
211 | }, 50);
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/MacWindowAnimActivity.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample;
2 |
3 | import android.os.Bundle;
4 | import android.view.Gravity;
5 | import android.view.MotionEvent;
6 | import android.view.View;
7 | import android.widget.Button;
8 | import android.widget.FrameLayout;
9 | import android.widget.TextView;
10 |
11 | import com.gplibs.magic_surface_view_sample.common.Direction;
12 | import com.gplibs.magic_surface_view_sample.common.MagicActivity;
13 | import com.gplibs.magic_surface_view_sample.updater.MacWindowAnimUpdater;
14 | import com.gplibs.magicsurfaceview.MagicScene;
15 | import com.gplibs.magicsurfaceview.MagicSceneBuilder;
16 | import com.gplibs.magicsurfaceview.MagicSurface;
17 | import com.gplibs.magicsurfaceview.MagicSurfaceView;
18 | import com.gplibs.magicsurfaceview.MagicUpdater;
19 | import com.gplibs.magicsurfaceview.MagicUpdaterListener;
20 |
21 | public class MacWindowAnimActivity extends MagicActivity implements View.OnTouchListener, View.OnClickListener {
22 |
23 | private MagicSurfaceView mSurfaceView;
24 | private TextView mTvContent;
25 |
26 | private Button mBtnLeft;
27 | private Button mBtnTop;
28 | private Button mBtnRight;
29 | private Button mBtnBottom;
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | setContentView(R.layout.activity_mac_window_anim);
35 | setTitle("MacWindowAnim");
36 |
37 | mSurfaceView = (MagicSurfaceView) findViewById(R.id.surface_view);
38 | mTvContent = (TextView) findViewById(R.id.tv_content);
39 |
40 | mBtnLeft = (Button) findViewById(R.id.btn_left);
41 | mBtnTop = (Button) findViewById(R.id.btn_top);
42 | mBtnRight = (Button) findViewById(R.id.btn_right);
43 | mBtnBottom = (Button) findViewById(R.id.btn_bottom);
44 |
45 | mBtnLeft.setOnClickListener(this);
46 | mBtnTop.setOnClickListener(this);
47 | mBtnRight.setOnClickListener(this);
48 | mBtnBottom.setOnClickListener(this);
49 |
50 | findViewById(R.id.view_left_container).setOnTouchListener(this);
51 | findViewById(R.id.view_top_container).setOnTouchListener(this);
52 | findViewById(R.id.view_right_container).setOnTouchListener(this);
53 | findViewById(R.id.view_bottom_container).setOnTouchListener(this);
54 | }
55 |
56 | @Override
57 | public boolean onTouch(View v, MotionEvent event) {
58 | boolean isVertical = false;
59 | Button btn = null;
60 | switch (v.getId()) {
61 | case R.id.view_left_container:
62 | btn = mBtnLeft;
63 | break;
64 | case R.id.view_top_container:
65 | btn = mBtnTop;
66 | isVertical = true;
67 | break;
68 | case R.id.view_right_container:
69 | btn = mBtnRight;
70 | break;
71 | case R.id.view_bottom_container:
72 | btn = mBtnBottom;
73 | isVertical = true;
74 | break;
75 | }
76 | updateBtnPosition(btn, isVertical, isVertical ? event.getX() : event.getY());
77 | return true;
78 | }
79 |
80 | @Override
81 | public void onClick(View v) {
82 | float center = 0.5f;
83 | int direction = Direction.BOTTOM;
84 | switch (v.getId()) {
85 | case R.id.btn_left:
86 | direction = Direction.LEFT;
87 | center = (v.getTop() + v.getHeight() / 2.f) / ((View)v.getParent()).getHeight();
88 | break;
89 | case R.id.btn_right:
90 | direction = Direction.RIGHT;
91 | center = (v.getTop() + v.getHeight() / 2.f) / ((View)v.getParent()).getHeight();
92 | break;
93 | case R.id.btn_top:
94 | direction = Direction.TOP;
95 | center = (v.getLeft() + v.getWidth() / 2.f) / ((View)v.getParent()).getWidth();
96 | break;
97 | case R.id.btn_bottom:
98 | direction = Direction.BOTTOM;
99 | center = (v.getLeft() + v.getWidth() / 2.f) / ((View)v.getParent()).getWidth();
100 | break;
101 | }
102 | if (isHide()) {
103 | show(center, direction);
104 | } else {
105 | hide(center, direction);
106 | }
107 | }
108 |
109 | private void hide(float center, int direction) {
110 | MacWindowAnimUpdater updater = new MacWindowAnimUpdater(true, direction, center, false);
111 | updater.addListener(new MagicUpdaterListener() {
112 | @Override
113 | public void onStart() {
114 | mTvContent.setVisibility(View.INVISIBLE);
115 | }
116 |
117 | @Override
118 | public void onStop() {
119 | mSurfaceView.setVisibility(View.GONE);
120 | // 释放资源
121 | mSurfaceView.release();
122 | }
123 | });
124 | MagicSurface s = new MagicSurface(mTvContent)
125 | .setGrid(getRowLineCount(direction), getColLineCount(direction))
126 | .setModelUpdater(updater);
127 | MagicScene scene = new MagicSceneBuilder(mSurfaceView)
128 | .addSurfaces(s)
129 | .build();
130 | mSurfaceView.setVisibility(View.VISIBLE);
131 | mSurfaceView.render(scene);
132 | }
133 |
134 | private void show(float center, int direction) {
135 | MacWindowAnimUpdater updater = new MacWindowAnimUpdater(false, direction, center, false);
136 | updater.addListener(new MagicUpdaterListener() {
137 | @Override
138 | public void onStart() {
139 | mTvContent.setVisibility(View.INVISIBLE);
140 | }
141 | @Override
142 | public void onStop() {
143 | mTvContent.setVisibility(View.VISIBLE);
144 | mSurfaceView.setVisibility(View.GONE);
145 | // 释放资源
146 | mSurfaceView.release();
147 | }
148 | });
149 | MagicSurface s = new MagicSurface(mTvContent)
150 | .setGrid(getRowLineCount(direction), getColLineCount(direction))
151 | .setModelUpdater(updater);
152 | mSurfaceView.setVisibility(View.VISIBLE);
153 | mSurfaceView.render(s);
154 | }
155 |
156 | private int getRowLineCount(int direction) {
157 | return Direction.isVertical(direction) ? 20 : 8;
158 | }
159 |
160 | private int getColLineCount(int direction) {
161 | return Direction.isVertical(direction) ? 8 : 20;
162 | }
163 |
164 | private boolean isHide() {
165 | return mTvContent.getVisibility() != View.VISIBLE;
166 | }
167 |
168 | private void updateBtnPosition(Button btn, boolean isVertical, float value) {
169 | if (value < 0) {
170 | value = 0;
171 | }
172 | View parent = (View) btn.getParent();
173 | float max = isVertical ? parent.getWidth() : parent.getHeight();
174 | if (value > max) {
175 | value = max;
176 | }
177 | FrameLayout.LayoutParams p = (FrameLayout.LayoutParams) btn.getLayoutParams();
178 | if (isVertical) {
179 | p.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
180 | p.leftMargin = (int) (value - btn.getWidth() / 2.0);
181 | } else {
182 | p.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
183 | p.topMargin = (int) (value - btn.getHeight() / 2.0);
184 | }
185 | btn.setLayoutParams(p);
186 | }
187 |
188 |
189 | // 设置Page转场动画
190 | @Override
191 | protected MagicUpdater getPageUpdater(boolean isHide) {
192 | return new MacWindowAnimUpdater(isHide, Direction.RIGHT, 0.184f, false);
193 | }
194 |
195 | }
196 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.os.Bundle;
8 | import android.support.annotation.LayoutRes;
9 | import android.support.annotation.NonNull;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.AdapterView;
13 | import android.widget.ArrayAdapter;
14 | import android.widget.Button;
15 | import android.widget.ListView;
16 |
17 | import com.gplibs.magic_surface_view_sample.common.Direction;
18 | import com.gplibs.magic_surface_view_sample.common.MagicActivity;
19 | import com.gplibs.magic_surface_view_sample.updater.VortexAnimUpdater;
20 | import com.gplibs.magic_surface_view_sample.updater.WaveAnimUpdater;
21 | import com.gplibs.magicsurfaceview.MagicSurfaceModelUpdater;
22 |
23 | import java.util.HashMap;
24 | import java.util.LinkedHashMap;
25 | import java.util.Map;
26 | import java.util.TreeMap;
27 |
28 | public class MainActivity extends MagicActivity {
29 |
30 | private Map.Entry>[] mArray;
31 |
32 | @Override
33 | protected void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_main);
36 | setTitle("MagicSurfaceViewSample");
37 | initData();
38 | initView();
39 | }
40 |
41 | private void initData() {
42 | Map> items = new LinkedHashMap<>();
43 | items.put("ScrapAnim", MultiScrapAnimActivity.class);
44 | items.put("MultiSlideAnim", MultiSlideAnimActivity.class);
45 | items.put("MacWindowAnim", MacWindowAnimActivity.class);
46 | items.put("WaveAnim", WaveAnimActivity.class);
47 | items.put("VortexAnim", VortexAnimActivity.class);
48 | items.put("MatrixAnimSample", MatrixAnimSampleActivity.class);
49 | items.put("LightSample", LightSampleActivity.class);
50 | mArray = new Map.Entry[items.size()];
51 | items.entrySet().toArray(mArray);
52 | }
53 |
54 | private void initView() {
55 | ((ListView) findViewById(R.id.list_view)).setAdapter(new Adapter(this, R.layout.item_activity));
56 | findViewById(R.id.tv_address).setOnClickListener(new View.OnClickListener() {
57 | @Override
58 | public void onClick(View v) {
59 | openGitHub();
60 | }
61 | });
62 | }
63 |
64 | @Override
65 | protected MagicSurfaceModelUpdater getPageUpdater(boolean isHide) {
66 | if (isHide) {
67 | return new VortexAnimUpdater(true);
68 | } else {
69 | return new WaveAnimUpdater(false, Direction.RIGHT, false);
70 | }
71 | }
72 |
73 | @Override
74 | protected int pageAnimRowCount() {
75 | return 60;
76 | }
77 |
78 | @Override
79 | protected int pageAnimColCount() {
80 | return 60;
81 | }
82 |
83 | private void start(Class extends Activity> activityClass) {
84 | startActivity(new Intent(this, activityClass));
85 | }
86 |
87 | private void openGitHub() {
88 | Intent intent = new Intent();
89 | intent.setAction("android.intent.action.VIEW");
90 | intent.setData(Uri.parse("http://github.com/gplibs"));
91 | startActivity(intent);
92 | }
93 |
94 | class Adapter extends ArrayAdapter>> {
95 | private int mResourceId;
96 |
97 | public Adapter(@NonNull Context context,@LayoutRes int resource) {
98 | super(context, resource);
99 | this.mResourceId = resource;
100 | }
101 |
102 | @Override
103 | public int getCount() {
104 | return mArray.length;
105 | }
106 |
107 | @Override
108 | public View getView(int position, View convertView, ViewGroup parent) {
109 | if (convertView == null){
110 | convertView = getLayoutInflater().inflate(mResourceId, null);
111 | }
112 | final Map.Entry> entry = mArray[position];
113 | ((Button) convertView).setText(entry.getKey());
114 | convertView.setOnClickListener(new View.OnClickListener() {
115 | @Override
116 | public void onClick(View v) {
117 | start(entry.getValue());
118 | }
119 | });
120 | return convertView;
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/MatrixAnimSampleActivity.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 | import android.widget.TextView;
6 |
7 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
8 | import com.gplibs.magic_surface_view_sample.common.MagicActivity;
9 | import com.gplibs.magicsurfaceview.MagicScene;
10 | import com.gplibs.magicsurfaceview.MagicSurface;
11 | import com.gplibs.magicsurfaceview.MagicSurfaceMatrixUpdater;
12 | import com.gplibs.magicsurfaceview.MagicSurfaceView;
13 | import com.gplibs.magicsurfaceview.MagicUpdaterListener;
14 | import com.gplibs.magicsurfaceview.Vec;
15 |
16 | /**
17 | * 矩形变换示例
18 | */
19 | public class MatrixAnimSampleActivity extends MagicActivity {
20 |
21 | private MagicSurfaceView mSurfaceView;
22 | private TextView mTvContent;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.activity_matrix_anim_sample);
28 | setTitle("MatrixAnimSample");
29 |
30 | mSurfaceView = (MagicSurfaceView) findViewById(R.id.surface_view);
31 | mTvContent = (TextView) findViewById(R.id.tv_content);
32 | findViewById(R.id.view_container).setOnClickListener(new View.OnClickListener() {
33 | @Override
34 | public void onClick(View v) {
35 | start();
36 | }
37 | });
38 | }
39 |
40 | @Override
41 | protected void onDestroy() {
42 | super.onDestroy();
43 | mSurfaceView.onDestroy();
44 | }
45 |
46 | private void start() {
47 | MatrixUpdater updater = new MatrixUpdater();
48 | updater.addListener(new MagicUpdaterListener() {
49 | @Override
50 | public void onStart() {
51 | mTvContent.setVisibility(View.INVISIBLE);
52 | }
53 | @Override
54 | public void onStop() {
55 | mTvContent.setVisibility(View.VISIBLE);
56 | mSurfaceView.setVisibility(View.GONE);
57 | // 释放资源
58 | mSurfaceView.release();
59 | }
60 | });
61 | MagicSurface s = new MagicSurface(mTvContent)
62 | .setGrid(2, 2)
63 | .drawGrid(false)
64 | .setMatrixUpdater(updater);
65 | mSurfaceView.setVisibility(View.VISIBLE);
66 | mSurfaceView.render(s);
67 | }
68 |
69 | /**
70 | * 矩阵变换示例
71 | */
72 | private static class MatrixUpdater extends MagicSurfaceMatrixUpdater {
73 |
74 | private FloatValueAnimator mAnimator;
75 | private float mAnimValue = 0;
76 |
77 | // y轴
78 | private Vec mAxis = new Vec(0, 1, 0);
79 | // 缩放量
80 | private Vec mScale = new Vec(1, 1, 1);
81 | // 位移量
82 | private Vec mTranslate = new Vec(0, 0, 0);
83 |
84 | public MatrixUpdater() {
85 | mAnimator = new FloatValueAnimator(1000);
86 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
87 | @Override
88 | public void onAnimationUpdate(float value) {
89 | mAnimValue = value;
90 | // 通知框架,数据改变,可以调用 update 方法进行更新
91 | notifyChanged();
92 | }
93 |
94 | @Override
95 | public void onStop() {
96 | // 通知框架,数据改变,可以调用 update 方法进行更新
97 | notifyChanged();
98 | }
99 | });
100 | }
101 |
102 | // 在绘制第一帧之前调用 (可以在此方法里进行一些初始化操作)
103 | @Override
104 | protected void willStart(MagicSurface surface) {
105 | mAnimValue = 0;
106 | mAnimator.reset();
107 | }
108 |
109 | // 在开始绘制后调用(绘制第一帧后调用,一般动画可以在此开始)
110 | @Override
111 | protected void didStart(MagicSurface surface) {
112 | mAnimator.start(false);
113 | }
114 |
115 | // 当调用Updater 的 stop() 方法之后,真正停止后会回调此方法
116 | @Override
117 | protected void didStop(MagicSurface surface) {
118 | mAnimator.stop();
119 | }
120 |
121 | /**
122 | * 在此方法里进行矩阵变换
123 | *
124 | * @param offset 为 model 相对场景中心的坐标偏移量, 如果不进行 offset 位移, model 就会显示在场景中心;
125 | *
126 | * 当使用 View 构造 MagicSurface 时,
127 | * View中心位置 相对 MagicSurfaceView中心位置 的坐标偏移量 在场景坐标系中的表现就是 offset。
128 | *
129 | * @param matrix model 矩阵
130 | */
131 | @Override
132 | protected void updateMatrix(MagicSurface surface, Vec offset, float[] matrix) {
133 |
134 | // 旋转角度
135 | float angle = 360.f * 2 * mAnimValue;
136 | float scale;
137 | float translateY;
138 |
139 | if (mAnimValue < 0.5f) { // 前一半时间
140 | // 从 1倍 缩小到 0.5倍
141 | scale = 0.5f + 0.5f * (0.5f - mAnimValue) / 0.5f;
142 | // 从 offset 处移到其y轴上方 0.8 位置处
143 | translateY = 0.8f * mAnimValue / 0.5f;
144 | } else { // 后一半时间
145 | // 从 0.5倍 放大到 1倍
146 | scale = 0.5f + 0.5f * (mAnimValue - 0.5f) / 0.5f;
147 | // 从 offset 上方 0.8 位置移到 offset 处
148 | translateY = 0.8f * (1 - mAnimValue) / 0.5f;
149 | }
150 |
151 | mScale.setXYZ(scale, scale, 1);
152 |
153 | mTranslate.copy(offset);
154 | mTranslate.add(0, translateY, 0);
155 |
156 | // 重置matrix
157 | reset(matrix);
158 | // 缩放
159 | scale(matrix, mScale);
160 | // 位移
161 | translate(matrix, mTranslate);
162 | // 绕 mAxis 旋转 angle 度。
163 | rotate(matrix, mAxis, angle);
164 |
165 | if (mAnimator.isStopped()) {
166 | stop();
167 | }
168 | }
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/MultiScrapAnimActivity.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 | import android.widget.TextView;
6 |
7 | import com.gplibs.magic_surface_view_sample.common.Direction;
8 | import com.gplibs.magic_surface_view_sample.common.MagicActivity;
9 | import com.gplibs.magic_surface_view_sample.updater.MultiScrapUpdater;
10 | import com.gplibs.magicsurfaceview.MagicMultiSurface;
11 | import com.gplibs.magicsurfaceview.MagicMultiSurfaceUpdater;
12 | import com.gplibs.magicsurfaceview.MagicSurfaceView;
13 | import com.gplibs.magicsurfaceview.MagicUpdater;
14 | import com.gplibs.magicsurfaceview.MagicUpdaterListener;
15 |
16 | public class MultiScrapAnimActivity extends MagicActivity {
17 |
18 | private MagicSurfaceView mSurfaceView;
19 | private TextView mTvTest;
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | setContentView(R.layout.activity_multi_scrap_anim);
25 | setTitle("ScrapAnim");
26 | mSurfaceView = (MagicSurfaceView) findViewById(R.id.magic_surface_view);
27 | mTvTest = (TextView) findViewById(R.id.tv_test);
28 |
29 | findViewById(R.id.view_container).setOnClickListener(new View.OnClickListener() {
30 | @Override
31 | public void onClick(View v) {
32 | if (mTvTest.getVisibility() == View.VISIBLE) {
33 | hide();
34 | } else {
35 | show();
36 | }
37 | }
38 | });
39 | }
40 |
41 | @Override
42 | protected void onDestroy() {
43 | super.onDestroy();
44 | mSurfaceView.onDestroy();
45 | }
46 |
47 | private void show() {
48 | MultiScrapUpdater mMultiUpdater = new MultiScrapUpdater(false, Direction.RIGHT);
49 | mMultiUpdater.addListener(new MagicUpdaterListener() {
50 | @Override
51 | public void onStart() {
52 | mTvTest.setVisibility(View.INVISIBLE);
53 | }
54 |
55 | @Override
56 | public void onStop() {
57 | mTvTest.setVisibility(View.VISIBLE);
58 | mSurfaceView.setVisibility(View.GONE);
59 | mSurfaceView.release();
60 | }
61 | });
62 | mSurfaceView.render(new MagicMultiSurface(mTvTest, 20, 10).setUpdater(mMultiUpdater));
63 | }
64 |
65 | private void hide() {
66 | MultiScrapUpdater mMultiUpdater = new MultiScrapUpdater(true, Direction.RIGHT);
67 | mMultiUpdater.addListener(new MagicUpdaterListener() {
68 | @Override
69 | public void onStart() {
70 | mTvTest.setVisibility(View.INVISIBLE);
71 | }
72 |
73 | @Override
74 | public void onStop() {
75 | mTvTest.setVisibility(View.INVISIBLE);
76 | mSurfaceView.setVisibility(View.GONE);
77 | mSurfaceView.release();
78 | }
79 | });
80 | mSurfaceView.render(new MagicMultiSurface(mTvTest, 20, 10).setUpdater(mMultiUpdater));
81 | }
82 |
83 | // 返回null禁用 单Surface转场动画
84 | @Override
85 | protected MagicUpdater getPageUpdater(boolean isHide) {
86 | return null;
87 | }
88 |
89 | // 启用多Surface转场动画
90 | @Override
91 | protected MagicMultiSurfaceUpdater getPageMultiUpdater(boolean isHide) {
92 | return new MultiScrapUpdater(isHide, Direction.BOTTOM);
93 | }
94 |
95 | // 纵向surface数量
96 | @Override
97 | protected int pageAnimRowCount() {
98 | return 20;
99 | }
100 |
101 | // 横向surface数量
102 | @Override
103 | protected int pageAnimColCount() {
104 | return 10;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/MultiSlideAnimActivity.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 | import android.widget.TextView;
6 |
7 | import com.gplibs.magic_surface_view_sample.common.Direction;
8 | import com.gplibs.magic_surface_view_sample.common.MagicActivity;
9 | import com.gplibs.magic_surface_view_sample.updater.MultiSlideUpdater;
10 | import com.gplibs.magicsurfaceview.MagicMultiSurface;
11 | import com.gplibs.magicsurfaceview.MagicMultiSurfaceUpdater;
12 | import com.gplibs.magicsurfaceview.MagicSurfaceView;
13 | import com.gplibs.magicsurfaceview.MagicUpdater;
14 | import com.gplibs.magicsurfaceview.MagicUpdaterListener;
15 |
16 | public class MultiSlideAnimActivity extends MagicActivity {
17 |
18 | private MagicSurfaceView mSurfaceView;
19 | private TextView mTvTest;
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | setContentView(R.layout.activity_multi_slide_anim);
25 | setTitle("MultiSlideAnim");
26 |
27 | mSurfaceView = (MagicSurfaceView) findViewById(R.id.magic_surface_view);
28 | mTvTest = (TextView) findViewById(R.id.tv_test);
29 | findViewById(R.id.view_container).setOnClickListener(new View.OnClickListener() {
30 | @Override
31 | public void onClick(View v) {
32 | if (mTvTest.getVisibility() == View.VISIBLE) {
33 | hide();
34 | } else {
35 | show();
36 | }
37 | }
38 | });
39 | }
40 |
41 | @Override
42 | protected void onDestroy() {
43 | super.onDestroy();
44 | mSurfaceView.onDestroy();
45 | }
46 |
47 | private void show() {
48 | MultiSlideUpdater updater = new MultiSlideUpdater(false, Direction.BOTTOM);
49 | updater.addListener(new MagicUpdaterListener() {
50 | @Override
51 | public void onStart() {
52 | mTvTest.setVisibility(View.INVISIBLE);
53 | }
54 |
55 | @Override
56 | public void onStop() {
57 | mSurfaceView.setVisibility(View.GONE);
58 | mTvTest.setVisibility(View.VISIBLE);
59 | mSurfaceView.release();
60 | }
61 | });
62 | mSurfaceView.render(new MagicMultiSurface(mTvTest, 150, 1).setUpdater(updater));
63 | }
64 |
65 | private void hide() {
66 | MultiSlideUpdater updater = new MultiSlideUpdater(true, Direction.BOTTOM);
67 | updater.addListener(new MagicUpdaterListener() {
68 | @Override
69 | public void onStart() {
70 | mTvTest.setVisibility(View.INVISIBLE);
71 | }
72 |
73 | @Override
74 | public void onStop() {
75 | mSurfaceView.setVisibility(View.GONE);
76 | mTvTest.setVisibility(View.INVISIBLE);
77 | mSurfaceView.release();
78 | }
79 | });
80 | mSurfaceView.render(new MagicMultiSurface(mTvTest, 150, 1).setUpdater(updater));
81 | }
82 |
83 | // 返回null禁用 单Surface转场动画
84 | @Override
85 | protected MagicUpdater getPageUpdater(boolean isHide) {
86 | return null;
87 | }
88 |
89 | // 启用多Surface转场动画
90 | @Override
91 | protected MagicMultiSurfaceUpdater getPageMultiUpdater(boolean isHide) {
92 | return new MultiSlideUpdater(isHide, Direction.TOP);
93 | }
94 |
95 | // 纵向surface数量
96 | @Override
97 | protected int pageAnimRowCount() {
98 | return 150;
99 | }
100 |
101 | // 横向surface数量
102 | @Override
103 | protected int pageAnimColCount() {
104 | return 1;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/VortexAnimActivity.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 | import android.widget.TextView;
6 |
7 | import com.gplibs.magic_surface_view_sample.common.Direction;
8 | import com.gplibs.magic_surface_view_sample.common.MagicActivity;
9 | import com.gplibs.magic_surface_view_sample.updater.MacWindowAnimUpdater;
10 | import com.gplibs.magic_surface_view_sample.updater.VortexAnimUpdater;
11 | import com.gplibs.magicsurfaceview.MagicScene;
12 | import com.gplibs.magicsurfaceview.MagicSurface;
13 | import com.gplibs.magicsurfaceview.MagicUpdater;
14 | import com.gplibs.magicsurfaceview.MagicUpdaterListener;
15 | import com.gplibs.magicsurfaceview.MagicSurfaceView;
16 |
17 | public class VortexAnimActivity extends MagicActivity {
18 |
19 | private MagicSurfaceView mSurfaceView;
20 | private TextView mTvContent;
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_vortex_anim);
26 | setTitle("VortexAnim");
27 |
28 | mSurfaceView = (MagicSurfaceView) findViewById(R.id.surface_view);
29 | mTvContent = (TextView) findViewById(R.id.tv_content);
30 | findViewById(R.id.view_container).setOnClickListener(new View.OnClickListener() {
31 | @Override
32 | public void onClick(View v) {
33 | if (mTvContent.getVisibility() == View.VISIBLE) {
34 | hide();
35 | } else {
36 | show();
37 | }
38 | }
39 | });
40 | }
41 |
42 | @Override
43 | protected void onDestroy() {
44 | super.onDestroy();
45 | mSurfaceView.onDestroy();
46 | }
47 |
48 | private void show() {
49 | VortexAnimUpdater updater = new VortexAnimUpdater(false);
50 | updater.addListener(new MagicUpdaterListener() {
51 | @Override
52 | public void onStart() {
53 | mTvContent.setVisibility(View.INVISIBLE);
54 | }
55 | @Override
56 | public void onStop() {
57 | mTvContent.setVisibility(View.VISIBLE);
58 | mSurfaceView.setVisibility(View.GONE);
59 | // 释放资源
60 | mSurfaceView.release();
61 | }
62 | });
63 | MagicSurface s = new MagicSurface(mTvContent)
64 | .setGrid(60, 60)
65 | .drawGrid(false)
66 | .setModelUpdater(updater);
67 | mSurfaceView.setVisibility(View.VISIBLE);
68 | mSurfaceView.render(s);
69 | }
70 |
71 | private void hide() {
72 | VortexAnimUpdater updater = new VortexAnimUpdater(true);
73 | updater.addListener(new MagicUpdaterListener() {
74 | @Override
75 | public void onStart() {
76 | mTvContent.setVisibility(View.INVISIBLE);
77 | }
78 | @Override
79 | public void onStop() {
80 | mSurfaceView.setVisibility(View.GONE);
81 | // 释放场景资源
82 | mSurfaceView.release();
83 | }
84 | });
85 | MagicSurface s = new MagicSurface(mTvContent)
86 | .setGrid(60, 60)
87 | .drawGrid(false)
88 | .setModelUpdater(updater);
89 | mSurfaceView.setVisibility(View.VISIBLE);
90 | mSurfaceView.render(s);
91 | }
92 |
93 | // 设置Page转场动画
94 | @Override
95 | protected MagicUpdater getPageUpdater(boolean isHide) {
96 | return new VortexAnimUpdater(isHide);
97 | }
98 |
99 | @Override
100 | protected int pageAnimRowCount() {
101 | return 60;
102 | }
103 |
104 | @Override
105 | protected int pageAnimColCount() {
106 | return 60;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/WaveAnimActivity.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 | import android.widget.TextView;
6 |
7 | import com.gplibs.magic_surface_view_sample.common.Direction;
8 | import com.gplibs.magic_surface_view_sample.common.MagicActivity;
9 | import com.gplibs.magic_surface_view_sample.updater.WaveAnimUpdater;
10 | import com.gplibs.magicsurfaceview.MagicScene;
11 | import com.gplibs.magicsurfaceview.MagicSurface;
12 | import com.gplibs.magicsurfaceview.MagicUpdaterListener;
13 | import com.gplibs.magicsurfaceview.MagicSurfaceView;
14 |
15 | public class WaveAnimActivity extends MagicActivity {
16 |
17 | private MagicSurfaceView mSurfaceView;
18 | private TextView mTvContent;
19 |
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.activity_wave_anim);
24 | setTitle("WaveAnim");
25 |
26 | mSurfaceView = (MagicSurfaceView) findViewById(R.id.surface_view);
27 | mTvContent = (TextView) findViewById(R.id.tv_content);
28 | findViewById(R.id.view_container).setOnClickListener(new View.OnClickListener() {
29 | @Override
30 | public void onClick(View v) {
31 | if (mTvContent.getVisibility() == View.VISIBLE) {
32 | hide(Direction.RIGHT);
33 | } else {
34 | show(Direction.RIGHT);
35 | }
36 | }
37 | });
38 | }
39 |
40 | @Override
41 | protected void onDestroy() {
42 | super.onDestroy();
43 | mSurfaceView.onDestroy();
44 | }
45 |
46 | private void show(int direction) {
47 | WaveAnimUpdater updater = new WaveAnimUpdater(false, direction, false);
48 | updater.addListener(new MagicUpdaterListener() {
49 | @Override
50 | public void onStart() {
51 | mTvContent.setVisibility(View.INVISIBLE);
52 | }
53 | @Override
54 | public void onStop() {
55 | mTvContent.setVisibility(View.VISIBLE);
56 | mSurfaceView.setVisibility(View.GONE);
57 | // 释放资源
58 | mSurfaceView.release();
59 | }
60 | });
61 | MagicSurface s = new MagicSurface(mTvContent)
62 | .setGrid(getRowLineCount(direction), getColLineCount(direction))
63 | .drawGrid(false)
64 | .setModelUpdater(updater);
65 | mSurfaceView.setVisibility(View.VISIBLE);
66 | mSurfaceView.render(s);
67 | }
68 |
69 | private void hide(int direction) {
70 | WaveAnimUpdater updater = new WaveAnimUpdater(true, direction, false);
71 | updater.addListener(new MagicUpdaterListener() {
72 | @Override
73 | public void onStart() {
74 | mTvContent.setVisibility(View.INVISIBLE);
75 | }
76 | @Override
77 | public void onStop() {
78 | mSurfaceView.setVisibility(View.GONE);
79 | // 释放资源
80 | mSurfaceView.release();
81 | }
82 | });
83 | MagicSurface s = new MagicSurface(mTvContent)
84 | .setGrid(getRowLineCount(direction), getColLineCount(direction))
85 | .drawGrid(false)
86 | .setModelUpdater(updater);
87 | mSurfaceView.setVisibility(View.VISIBLE);
88 | mSurfaceView.render(s);
89 | }
90 |
91 | private int getRowLineCount(int direction) {
92 | return Direction.isVertical(direction) ? 50 : 8;
93 | }
94 |
95 | private int getColLineCount(int direction) {
96 | return Direction.isVertical(direction) ? 8 : 50;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/common/AnimHelper.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.common;
2 |
3 | import com.gplibs.magicsurfaceview.MagicBaseSurface;
4 | import com.gplibs.magicsurfaceview.ReusableVec;
5 | import com.gplibs.magicsurfaceview.Vec;
6 | import com.gplibs.magicsurfaceview.VecPool;
7 |
8 | public class AnimHelper {
9 |
10 | public static final int MOVE_TYPE_SCENE = 0;
11 | public static final int MOVE_TYPE_SELF = 1;
12 |
13 | private float mAnimValue;
14 | private int mDirection;
15 | private MagicBaseSurface mSurface;
16 | private float mTotalDistanceScene;
17 | private float mTotalDistanceSelf;
18 | private float mBeginPos = 0, mReverseBeginPos = 0, mSurfaceSize = 1;
19 |
20 | public AnimHelper(MagicBaseSurface surface, int direction, boolean isHide) {
21 | mSurface = surface;
22 | mDirection = direction;
23 | mAnimValue = isHide ? 0 : 1;
24 | init();
25 | }
26 |
27 | public void update(float animValue) {
28 | mAnimValue = animValue;
29 | }
30 |
31 | public float getStartAnimTime(Vec pos, boolean reverse, float totalStartingTime) {
32 | float p = (mDirection == Direction.TOP || mDirection == Direction.BOTTOM) ? pos.y() : pos.x();
33 | float begin = reverse ? mReverseBeginPos : mBeginPos;
34 | return Math.abs(p - begin) / mSurfaceSize * totalStartingTime;
35 | }
36 |
37 | public float getStartAnimTime(int index, int count, boolean reverse, float totalStartingTime) {
38 | float start = 0;
39 | float end = count - 1;
40 | switch (mDirection) {
41 | case Direction.TOP:
42 | case Direction.LEFT:
43 | start = reverse ? count - 1 : 0;
44 | end = reverse ? 0 : count - 1;
45 | break;
46 | case Direction.RIGHT:
47 | case Direction.BOTTOM:
48 | start = reverse ? 0 : count - 1;
49 | end = reverse ? count - 1 : 0;
50 | break;
51 | }
52 | return Math.abs((index - start) / (end - start)) * totalStartingTime;
53 | }
54 |
55 | public float getAnimProgress(float startTime, float animTime) {
56 | float endTime = startTime + animTime;
57 | if (endTime > 1) {
58 | endTime = 1;
59 | }
60 | if (mAnimValue < startTime ) {
61 | return 0;
62 | } else if (mAnimValue >= startTime && mAnimValue < endTime) {
63 | float r = (mAnimValue - startTime) / (endTime - startTime);
64 | return r * r;
65 | } else {
66 | return 1;
67 | }
68 | }
69 |
70 | public float getMoveDistance(int moveType, float beginTime, float movingTime) {
71 | return getMoveDistance(moveType == MOVE_TYPE_SELF ? mTotalDistanceSelf : mTotalDistanceScene, beginTime, movingTime);
72 | }
73 |
74 | public float getMoveDistance(float totalDistance, float beginTime, float movingTime) {
75 | float r = getAnimProgress(beginTime, movingTime);
76 | if (mDirection == Direction.TOP || mDirection == Direction.RIGHT) {
77 | return totalDistance * r;
78 | } else {
79 | return -totalDistance * r;
80 | }
81 | }
82 |
83 | private void init() {
84 | ReusableVec surfacePos = VecPool.get(3);
85 | ReusableVec scenePos = VecPool.get(3);
86 | ReusableVec surfacePos1 = VecPool.get(3);
87 | boolean isVertical = false;
88 |
89 | if (mDirection == Direction.TOP) {
90 | mSurface.getPosition(0, 1, surfacePos);
91 | mSurface.getScene().getPosition(0, 0, scenePos);
92 | mSurface.getPosition(0, 0, surfacePos1);
93 | isVertical = true;
94 | } else if (mDirection == Direction.BOTTOM) {
95 | mSurface.getPosition(0, 0, surfacePos);
96 | mSurface.getScene().getPosition(0, 1, scenePos);
97 | mSurface.getPosition(0, 1, surfacePos1);
98 | isVertical = true;
99 | } else if (mDirection == Direction.LEFT) {
100 | mSurface.getPosition(1, 0, surfacePos);
101 | mSurface.getScene().getPosition(0, 0, scenePos);
102 | mSurface.getPosition(0, 0, surfacePos1);
103 | isVertical = false;
104 | } else if (mDirection == Direction.RIGHT) {
105 | mSurface.getPosition(0, 0, surfacePos);
106 | mSurface.getScene().getPosition(1, 0, scenePos);
107 | mSurface.getPosition(1, 0, surfacePos1);
108 | isVertical = false;
109 | }
110 |
111 | if (isVertical) {
112 | mReverseBeginPos = surfacePos.y();
113 | mBeginPos = surfacePos1.y();
114 | mSurfaceSize = mSurface.getHeight();
115 | mTotalDistanceScene = Math.abs(scenePos.y() - surfacePos.y());
116 | mTotalDistanceSelf = Math.abs(surfacePos1.y() - surfacePos.y());
117 | } else {
118 | mReverseBeginPos = surfacePos.x();
119 | mBeginPos = surfacePos1.x();
120 | mSurfaceSize = mSurface.getWidth();
121 | mTotalDistanceScene = Math.abs(scenePos.x() - surfacePos.x());
122 | mTotalDistanceSelf = Math.abs(surfacePos1.x() - surfacePos.x());
123 | }
124 |
125 | scenePos.free();
126 | surfacePos1.free();
127 | surfacePos.free();
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/common/Direction.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.common;
2 |
3 | public class Direction {
4 | public final static int LEFT = 0;
5 | public final static int TOP = 1;
6 | public final static int RIGHT = 2;
7 | public final static int BOTTOM = 3;
8 |
9 | public static boolean isVertical(int direction) {
10 | return direction == TOP || direction == BOTTOM;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/common/FloatValueAnimator.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.common;
2 |
3 | import android.animation.Animator;
4 | import android.animation.TimeInterpolator;
5 | import android.animation.ValueAnimator;
6 | import android.os.Handler;
7 | import android.os.Looper;
8 | import android.view.animation.BounceInterpolator;
9 | import android.view.animation.LinearInterpolator;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | /**
15 | * 0~1 或者 1~0 的ValueAnimator
16 | */
17 | public class FloatValueAnimator implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
18 |
19 | public interface FloatValueAnimatorListener {
20 | void onAnimationUpdate(float value);
21 | void onStop();
22 | }
23 |
24 | private final int STATE_NONE = 0;
25 | private final int STATE_RUNNING = 1;
26 | private final int STATE_STOPPED = 2;
27 |
28 | private int mState = STATE_NONE;
29 | private boolean mStopping = false;
30 | private ValueAnimator mAnimator;
31 | private int mDuration = 600;
32 | private TimeInterpolator mInterpolator;
33 | private List mListeners = new ArrayList<>(2);
34 |
35 | public FloatValueAnimator(int duration) {
36 | mDuration = duration;
37 | }
38 |
39 | public void addListener(FloatValueAnimatorListener listener) {
40 | if (!mListeners.contains(listener)) {
41 | mListeners.add(listener);
42 | }
43 | }
44 |
45 | public void removeListener(FloatValueAnimatorListener listener) {
46 | if (mListeners.contains(listener)) {
47 | mListeners.remove(listener);
48 | }
49 | }
50 |
51 | public void setDuration(int duration) {
52 | mDuration = duration;
53 | }
54 |
55 | public void setInterpolator(TimeInterpolator interpolator) {
56 | this.mInterpolator = interpolator;
57 | }
58 |
59 | @Override
60 | public void onAnimationUpdate(ValueAnimator animation) {
61 | onAnimValueChanged((float) animation.getAnimatedValue());
62 | }
63 |
64 | @Override
65 | public void onAnimationStart(Animator animation) {
66 | }
67 |
68 | @Override
69 | public void onAnimationEnd(Animator animation) {
70 | mState = STATE_STOPPED;
71 | mAnimator = null;
72 | onStop();
73 | }
74 |
75 | @Override
76 | public void onAnimationCancel(Animator animation) {
77 | mState = STATE_STOPPED;
78 | mAnimator = null;
79 | onStop();
80 | }
81 |
82 | @Override
83 | public void onAnimationRepeat(Animator animation) {
84 | }
85 |
86 | public void reset() {
87 | mState = STATE_NONE;
88 | }
89 |
90 | public boolean isStopped() {
91 | return mState == STATE_STOPPED;
92 | }
93 |
94 | public boolean isRunning() {
95 | return mState == STATE_RUNNING;
96 | }
97 |
98 | public synchronized void start(final boolean isReverse) {
99 | if (mState == STATE_RUNNING) {
100 | return;
101 | }
102 | mState = STATE_RUNNING;
103 | new Handler(Looper.getMainLooper()).post(new Runnable() {
104 | @Override
105 | public void run() {
106 | if (isReverse) {
107 | mAnimator = ValueAnimator.ofFloat(1, 0);
108 | } else {
109 | mAnimator = ValueAnimator.ofFloat(0, 1);
110 | }
111 | if (mInterpolator != null) {
112 | mAnimator.setInterpolator(mInterpolator);
113 | }
114 | mAnimator.addUpdateListener(FloatValueAnimator.this);
115 | mAnimator.addListener(FloatValueAnimator.this);
116 | mAnimator.setRepeatCount(0);
117 | mAnimator.setDuration(mDuration);
118 | mAnimator.start();
119 | }
120 | });
121 | }
122 |
123 | public synchronized void stop() {
124 | if (mAnimator == null) {
125 | return;
126 | }
127 | if (mStopping) {
128 | return;
129 | }
130 | mStopping = true;
131 | new Handler(Looper.getMainLooper()).post(new Runnable() {
132 | @Override
133 | public void run() {
134 | if (mAnimator != null) {
135 | mAnimator.cancel();
136 | mAnimator = null;
137 | }
138 | mStopping = false;
139 | }
140 | });
141 | }
142 |
143 | private void onAnimValueChanged(float animValue) {
144 | for(int i = 0; i < mListeners.size(); ++i) {
145 | if (mListeners.get(i) != null) {
146 | mListeners.get(i).onAnimationUpdate(animValue);
147 | }
148 | }
149 | }
150 |
151 | private void onStop() {
152 | for(int i = 0; i < mListeners.size(); ++i) {
153 | if (mListeners.get(i) != null) {
154 | mListeners.get(i).onStop();
155 | }
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/common/MagicActivity.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.common;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.ColorRes;
5 | import android.support.annotation.LayoutRes;
6 | import android.support.v4.content.ContextCompat;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.widget.FrameLayout;
11 | import android.widget.TextView;
12 |
13 | import com.gplibs.magic_surface_view_sample.R;
14 | import com.gplibs.magic_surface_view_sample.updater.WaveAnimUpdater;
15 | import com.gplibs.magicsurfaceview.MagicMultiSurface;
16 | import com.gplibs.magicsurfaceview.MagicMultiSurfaceUpdater;
17 | import com.gplibs.magicsurfaceview.MagicSurface;
18 | import com.gplibs.magicsurfaceview.MagicSurfaceMatrixUpdater;
19 | import com.gplibs.magicsurfaceview.MagicSurfaceModelUpdater;
20 | import com.gplibs.magicsurfaceview.MagicSurfaceView;
21 | import com.gplibs.magicsurfaceview.MagicUpdater;
22 | import com.gplibs.magicsurfaceview.MagicUpdaterListener;
23 |
24 | public abstract class MagicActivity extends AppCompatActivity {
25 |
26 | // 页面可视部分的根View
27 | private View mPageViewContainer;
28 | // 用于页面转场动画的 MagicSurfaceView
29 | private MagicSurfaceView mPageSurfaceView;
30 | // 页面TitleBar
31 | private View mPageTitleBar;
32 | // 页面内容容器
33 | private FrameLayout mFlPageContent;
34 | // Title TextView
35 | private TextView mTvPageTitle;
36 |
37 | @Override
38 | protected void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | super.setContentView(R.layout.activity_magic);
41 | mPageViewContainer = findViewById(R.id.page_view_container);
42 | mPageSurfaceView = (MagicSurfaceView) findViewById(R.id.page_surface_view);
43 | mPageTitleBar = findViewById(R.id.page_title_bar);
44 | mFlPageContent = (FrameLayout) findViewById(R.id.fl_page_content);
45 | mTvPageTitle = (TextView) findViewById(R.id.tv_page_title);
46 |
47 | // 进行入场动画
48 | if (!show()) {
49 | mPageViewContainer.setVisibility(View.VISIBLE);
50 | }
51 | }
52 |
53 | @Override
54 | protected void onDestroy() {
55 | super.onDestroy();
56 | mPageSurfaceView.onDestroy();
57 | }
58 |
59 | @Override
60 | public void onBackPressed() {
61 | // 进行离场动画
62 | if(!hide()) {
63 | finish();
64 | }
65 | }
66 |
67 | @Override
68 | public void setTitle(CharSequence title) {
69 | mTvPageTitle.setText(title);
70 | }
71 |
72 | @Override
73 | public void setTitle(int titleId) {
74 | mTvPageTitle.setText(titleId);
75 | }
76 |
77 | @Override
78 | public void setContentView(@LayoutRes int layoutResID) {
79 | LayoutInflater.from(this).inflate(layoutResID, mFlPageContent, true);
80 | }
81 |
82 | protected MagicSurfaceView getPageSurfaceView() {
83 | return mPageSurfaceView;
84 | }
85 |
86 | protected View getPageViewContainer() {
87 | return mPageViewContainer;
88 | }
89 |
90 | protected void showPage() {
91 | mPageViewContainer.setVisibility(View.VISIBLE);
92 | }
93 |
94 | protected void hidePage() {
95 | mPageViewContainer.setVisibility(View.INVISIBLE);
96 | }
97 |
98 | protected void hidePageTitleBar() {
99 | mPageTitleBar.setVisibility(View.GONE);
100 | }
101 |
102 | protected void setPageBackground(@ColorRes int colorResource) {
103 | mPageViewContainer.setBackgroundColor(ContextCompat.getColor(this, colorResource));
104 | }
105 |
106 | protected void setPageContentBg(@ColorRes int colorResource) {
107 | mFlPageContent.setBackgroundResource(colorResource);
108 | }
109 |
110 | /**
111 | * 获取页面转场动画对应的 Updater
112 | * @param isHide true:离场 false:入场
113 | * @return
114 | */
115 | protected MagicUpdater getPageUpdater(boolean isHide) {
116 | if (isHide) {
117 | return new WaveAnimUpdater(true, Direction.RIGHT, false);
118 | } else {
119 | return new WaveAnimUpdater(false, Direction.RIGHT, false);
120 | }
121 | }
122 |
123 | /**
124 | * 获取页面碎片化转场动画对应的 Updater
125 | * @param isHide true:离场 false:入场
126 | * @return
127 | */
128 | protected MagicMultiSurfaceUpdater getPageMultiUpdater(boolean isHide) {
129 | return null;
130 | }
131 |
132 | /**
133 | * 页面转场动画对应 SurfaceModel 行数
134 | * @return
135 | */
136 | protected int pageAnimRowCount() {
137 | return 30;
138 | }
139 |
140 | /**
141 | * 页面转场动画对应 SurfaceModel 列数
142 | * @return
143 | */
144 | protected int pageAnimColCount() {
145 | return 30;
146 | }
147 |
148 | /**
149 | * 页面转场动画入场动画完成后调用
150 | * @return
151 | */
152 | protected void onPageAnimEnd() {
153 | }
154 |
155 | /**
156 | * 开始入场动画
157 | * @return
158 | */
159 | private boolean show() {
160 | MagicUpdater updater = getPageUpdater(false);
161 | if (updater != null) {
162 | return showWithSurface(updater);
163 | }
164 | MagicMultiSurfaceUpdater multiUpdater = getPageMultiUpdater(false);
165 | if (multiUpdater != null) {
166 | return showWithMultiSurface(multiUpdater);
167 | }
168 | return false;
169 | }
170 |
171 | private boolean showWithSurface(MagicUpdater updater) {
172 | updater.addListener(new MagicUpdaterListener() {
173 | @Override
174 | public void onStart() {
175 | mPageViewContainer.setVisibility(View.INVISIBLE);
176 | }
177 | @Override
178 | public void onStop() {
179 | mPageViewContainer.setVisibility(View.VISIBLE);
180 | mPageSurfaceView.setVisibility(View.GONE);
181 | // 动画完成释放资源
182 | mPageSurfaceView.release();
183 | onPageAnimEnd();
184 | }
185 | });
186 | final MagicSurface s = new MagicSurface(mPageViewContainer)
187 | .setGrid(pageAnimRowCount(), pageAnimColCount())
188 | .drawGrid(false);
189 | if (updater instanceof MagicSurfaceMatrixUpdater) {
190 | s.setMatrixUpdater((MagicSurfaceMatrixUpdater) updater);
191 | } else {
192 | s.setModelUpdater((MagicSurfaceModelUpdater) updater);
193 | }
194 | mPageSurfaceView.setVisibility(View.VISIBLE);
195 | mPageSurfaceView.render(s);
196 | return true;
197 | }
198 |
199 | private boolean showWithMultiSurface(MagicMultiSurfaceUpdater updater) {
200 | updater.addListener(new MagicUpdaterListener() {
201 | @Override
202 | public void onStart() {
203 | mPageViewContainer.setVisibility(View.INVISIBLE);
204 | }
205 | @Override
206 | public void onStop() {
207 | mPageViewContainer.setVisibility(View.VISIBLE);
208 | mPageSurfaceView.setVisibility(View.GONE);
209 | // 动画完成释放资源
210 | mPageSurfaceView.release();
211 | onPageAnimEnd();
212 | }
213 | });
214 | final MagicMultiSurface s = new MagicMultiSurface(mPageViewContainer, pageAnimRowCount(), pageAnimColCount());
215 | s.setUpdater(updater);
216 | mPageSurfaceView.setVisibility(View.VISIBLE);
217 | mPageSurfaceView.render(s);
218 | return true;
219 | }
220 |
221 |
222 | /**
223 | * 开始离场动画
224 | * @return
225 | */
226 | private boolean hide() {
227 | MagicUpdater updater = getPageUpdater(true);
228 | if (updater != null) {
229 | return hideWithSurface(updater);
230 | }
231 |
232 | MagicMultiSurfaceUpdater multiUpdater = getPageMultiUpdater(true);
233 | if (multiUpdater != null) {
234 | return hideWithMultiSurface(multiUpdater);
235 | }
236 | return false;
237 | }
238 |
239 | private boolean hideWithSurface(MagicUpdater updater) {
240 | updater.addListener(new MagicUpdaterListener() {
241 | @Override
242 | public void onStart() {
243 | mPageViewContainer.setVisibility(View.INVISIBLE);
244 | }
245 | @Override
246 | public void onStop() {
247 | mPageSurfaceView.setVisibility(View.GONE);
248 | // 动画完成释放资源
249 | mPageSurfaceView.release();
250 | finish();
251 | }
252 | });
253 | MagicSurface s = new MagicSurface(mPageViewContainer)
254 | .setGrid(pageAnimRowCount(), pageAnimColCount())
255 | .drawGrid(false);
256 | if (updater instanceof MagicSurfaceMatrixUpdater) {
257 | s.setMatrixUpdater((MagicSurfaceMatrixUpdater) updater);
258 | } else {
259 | s.setModelUpdater((MagicSurfaceModelUpdater) updater);
260 | }
261 | mPageSurfaceView.setVisibility(View.VISIBLE);
262 | mPageSurfaceView.render(s);
263 | return true;
264 | }
265 |
266 | private boolean hideWithMultiSurface(MagicMultiSurfaceUpdater updater) {
267 | updater.addListener(new MagicUpdaterListener() {
268 | @Override
269 | public void onStart() {
270 | mPageViewContainer.setVisibility(View.INVISIBLE);
271 | }
272 | @Override
273 | public void onStop() {
274 | mPageSurfaceView.setVisibility(View.GONE);
275 | // 动画完成释放资源
276 | mPageSurfaceView.release();
277 | finish();
278 | }
279 | });
280 | final MagicMultiSurface s = new MagicMultiSurface(mPageViewContainer, pageAnimRowCount(), pageAnimColCount());
281 | s.setUpdater(updater);
282 | mPageSurfaceView.setVisibility(View.VISIBLE);
283 | mPageSurfaceView.render(s);
284 | return true;
285 | }
286 |
287 | }
288 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/common/RandomNumber.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.common;
2 |
3 | public class RandomNumber {
4 |
5 | float mMin;
6 | float mMax;
7 | float[] mNumbers;
8 |
9 | public RandomNumber(int count, float min, float max) {
10 | mNumbers = new float[count];
11 | mMin = min;
12 | mMax = max;
13 | }
14 |
15 | public float get(int index) {
16 | if (mNumbers[index] == 0) {
17 | mNumbers[index] = mMin + (float) Math.random() * (mMax - mMin);
18 | }
19 | return mNumbers[index];
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/launch/LaunchActivity.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.launch;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.View;
7 | import android.widget.Button;
8 |
9 | import com.gplibs.magic_surface_view_sample.common.MagicActivity;
10 | import com.gplibs.magic_surface_view_sample.MainActivity;
11 | import com.gplibs.magic_surface_view_sample.R;
12 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
13 | import com.gplibs.magicsurfaceview.MagicScene;
14 | import com.gplibs.magicsurfaceview.MagicSceneBuilder;
15 | import com.gplibs.magicsurfaceview.MagicSurface;
16 | import com.gplibs.magicsurfaceview.MagicUpdater;
17 | import com.gplibs.magicsurfaceview.MagicUpdaterListener;
18 | import com.gplibs.magicsurfaceview.PointLight;
19 |
20 | /**
21 | * 环境光: 开始黑色 STEP3~1 由黑变白色
22 | * 背景: 0~STEP1由中心开始逐渐显示
23 | * 光源: STEP1~STEP2 由黑变亮 STEP2~STEP3 从左到右 STEP3~1 逐渐消失(颜色变为0)
24 | * 文本: STEP2~STEP3 从左到右与光源同步显示
25 | * 按钮: STEP3~1 逐渐显示出来
26 | */
27 | public class LaunchActivity extends MagicActivity {
28 |
29 | static final float STEP1 = 0.12f;
30 | static final float STEP2 = 0.3f;
31 | static final float STEP3 = 0.8f;
32 |
33 | private FloatValueAnimator mAnimator = new FloatValueAnimator(2000);
34 |
35 | private PointLight mLight = new PointLight(0XFFFFFFFF, 0, 0, 0.1f);
36 | private int endAnimatorCount = 0;
37 |
38 | private View mViewText;
39 | private Button mBtnEnter;
40 |
41 | // 各Updater运行时间段都是按时间线错开的,btnMatrixUpdater 和 btnModelUpdater是需要同步运行的,所以可以都分到一组,在一个线程运行。
42 |
43 | // 场景动画
44 | private LaunchSceneUpdater sceneUpdater = new LaunchSceneUpdater(mAnimator, 1);
45 | // 背景模型动画
46 | private LaunchBackgroundUpdater backgroundUpdater = new LaunchBackgroundUpdater(mAnimator, 1);
47 | // 文本模型动画
48 | private LaunchTextModelUpdater textModelUpdater = new LaunchTextModelUpdater(mAnimator, 1);
49 | // 按钮矩阵动画
50 | private LaunchButtonMatrixUpdater btnMatrixUpdater = new LaunchButtonMatrixUpdater(mAnimator, 1);
51 | // 按钮模型动画
52 | private LaunchButtonModelUpdater btnModelUpdater = new LaunchButtonModelUpdater(mAnimator, 1);
53 |
54 | private MagicUpdaterListener updaterListener = new MagicUpdaterListener() {
55 | @Override
56 | public void onStart() {
57 |
58 | }
59 | @Override
60 | public void onStop() {
61 | if (++endAnimatorCount == 5) { // 所有动画结束后调用
62 | // 显示真实页面 和 文本、按钮
63 | showPage();
64 | mBtnEnter.setVisibility(View.VISIBLE);
65 | mViewText.setVisibility(View.VISIBLE);
66 |
67 | // 隐藏 MagicSurfaceView
68 | getPageSurfaceView().setVisibility(View.GONE);
69 |
70 | // 动画完成释放资源
71 | getPageSurfaceView().release();
72 | }
73 | }
74 | };
75 |
76 | @Override
77 | protected void onCreate(Bundle savedInstanceState) {
78 | super.onCreate(savedInstanceState);
79 | setPageBackground(R.color.white);
80 | setPageContentBg(R.color.white);
81 | hidePageTitleBar();
82 | hidePage(); // 起始页动画是个入场的过程,开始需要隐藏整个页面(隐藏必须使用INVISIBLE 不要使用 GONE)
83 | setContentView(R.layout.activity_launch);
84 |
85 | initViews();
86 | initMagicObjects();
87 |
88 | render();
89 | }
90 |
91 | private void initViews() {
92 | mViewText = findViewById(R.id.view_text);
93 | mBtnEnter = (Button) findViewById(R.id.btn_enter);
94 | mBtnEnter.setOnClickListener(new View.OnClickListener() {
95 | @Override
96 | public void onClick(View v) {
97 | startActivity(new Intent(LaunchActivity.this, MainActivity.class));
98 | mBtnEnter.postDelayed(new Runnable() {
99 | @Override
100 | public void run() {
101 | finish();
102 | }
103 | }, 2000);
104 | }
105 | });
106 | // 动画是个入场的过程,开始需要隐藏 (隐藏必须使用INVISIBLE 不要使用 GONE)
107 | mViewText.setVisibility(View.INVISIBLE);
108 | // 动画是个入场的过程,开始需要隐藏 (隐藏必须使用INVISIBLE 不要使用 GONE)
109 | mBtnEnter.setVisibility(View.INVISIBLE);
110 | }
111 |
112 | private void initMagicObjects() {
113 | backgroundUpdater.addListener(updaterListener);
114 | sceneUpdater.addListener(updaterListener);
115 | btnMatrixUpdater.addListener(updaterListener);
116 | textModelUpdater.addListener(updaterListener);
117 | btnModelUpdater.addListener(updaterListener);
118 | }
119 |
120 | /**
121 | * 返回 null 禁用Page转场动画
122 | */
123 | @Override
124 | protected MagicUpdater getPageUpdater(boolean isHide) {
125 | return null;
126 | }
127 |
128 | private void render() {
129 | MagicSurface bgSurface = new MagicSurface(getPageViewContainer())
130 | .setGrid(60, 60)
131 | .setModelUpdater(backgroundUpdater);
132 |
133 | MagicSurface textSurface = new MagicSurface(mViewText)
134 | .setGrid(2, 600)
135 | .setEnableDepthTest(false)
136 | .setModelUpdater(textModelUpdater)
137 | .setVisible(false);
138 |
139 | MagicSurface btnSurface = new MagicSurface(mBtnEnter)
140 | .setGrid(30, 5)
141 | .setEnableDepthTest(false)
142 | .setMatrixUpdater(btnMatrixUpdater)
143 | .setModelUpdater(btnModelUpdater)
144 | .setVisible(false);
145 |
146 | MagicScene scene = new MagicSceneBuilder(getPageSurfaceView())
147 | .ambientColor(0XFF000000)
148 | .addLights(mLight)
149 | .setUpdater(sceneUpdater)
150 | .addSurfaces(bgSurface, textSurface, btnSurface)
151 | .build();
152 | getPageSurfaceView().render(scene);
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/launch/LaunchBackgroundUpdater.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.launch;
2 |
3 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
4 | import com.gplibs.magicsurfaceview.MagicSurface;
5 | import com.gplibs.magicsurfaceview.MagicSurfaceModelUpdater;
6 | import com.gplibs.magicsurfaceview.ReusableVec;
7 | import com.gplibs.magicsurfaceview.SurfaceModel;
8 | import com.gplibs.magicsurfaceview.Vec;
9 | import com.gplibs.magicsurfaceview.VecPool;
10 |
11 |
12 | /**
13 | * 0~STEP1
14 | */
15 | class LaunchBackgroundUpdater extends MagicSurfaceModelUpdater {
16 |
17 | private final float WAVE_LENGTH = 0.5f;
18 |
19 | private FloatValueAnimator mAnimator;
20 | private float mAnimValue = 0;
21 |
22 | private float mMaxRadius;
23 | private float mRatio = 0;
24 | private boolean mIsCompleted = false;
25 |
26 | LaunchBackgroundUpdater(FloatValueAnimator animator, int group) {
27 | super(group);
28 | mAnimator = animator;
29 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
30 | @Override
31 | public void onAnimationUpdate(float value) {
32 | mAnimValue = value;
33 | // 通知框架,数据改变,可以调用 update 方法进行更新
34 | notifyChanged();
35 | }
36 |
37 | @Override
38 | public void onStop() {
39 | // 通知框架,数据改变,可以调用 update 方法进行更新
40 | notifyChanged();
41 | }
42 | });
43 | }
44 |
45 | // 在绘制第一帧之前调用 (可以在此方法里进行一些初始化操作)
46 | @Override
47 | protected void willStart(MagicSurface surface) {
48 | mMaxRadius = getRadius(surface.getModel(), 0, 0);
49 | }
50 |
51 | // 在开始绘制后调用(绘制第一帧后调用,一般动画可以在此开始)
52 | @Override
53 | protected void didStart(MagicSurface surface) {
54 | mAnimator.start(false);
55 | }
56 |
57 | // 当调用Updater 的 stop() 方法之后,真正停止后会回调此方法
58 | @Override
59 | protected void didStop(MagicSurface surface) {
60 | mAnimator.stop();
61 | }
62 |
63 | @Override
64 | protected void updateBegin(MagicSurface surface) {
65 | }
66 |
67 | /**
68 | * 修改网格模型 r行, c列处 的坐标及颜色, 修改后的值存到 outPos 和 outColor
69 | * (只需要修改网格模型各行各列点及可,点与点之间的坐标和颜色由 openGL 自动进行插值计算完成)
70 | * 注:此方法执行频率非常高;一般不要有分配新的堆内存的逻辑,会频繁产生gc操作影响性能,可以使用全局变量或者ReusableVec、VecPool
71 | *
72 | * @param surface
73 | * @param r 行
74 | * @param c 列
75 | * @param outPos 默认值为 r行c列点包含偏移量的原始坐标, 计算完成后的新坐标要更新到此变量
76 | * @param outColor 默认值为 rgba(1,1,1,1), 计算完成后的新颜色要更新到此变量
77 | */
78 | @Override
79 | protected void updatePosition(MagicSurface surface, int r, int c, Vec outPos, Vec outColor) {
80 | if (mIsCompleted) {
81 | return;
82 | }
83 | mRatio = 1;
84 | if (mAnimValue <= LaunchActivity.STEP1) {
85 | mRatio = mAnimValue / LaunchActivity.STEP1;
86 | }
87 | float startRadius = mRatio * (mMaxRadius + WAVE_LENGTH)- WAVE_LENGTH;
88 | float radius = getRadius(outPos);
89 | float offset = radius - startRadius;
90 | if (offset < 0) {
91 | outColor.setColor(0XFFFFFFFF);
92 | } else if (offset > WAVE_LENGTH) {
93 | outColor.a(0);
94 | } else {
95 | float ratio = offset / WAVE_LENGTH;
96 | float a = ratio - 0.6f;
97 | if (a < 0) {
98 | a = 1;
99 | } else {
100 | a = (0.4f - a) / 0.4f;
101 | }
102 | outColor.setRGBA(1 - ratio, 1 - ratio, 1, a);
103 | }
104 | }
105 |
106 | @Override
107 | protected void updateEnd(MagicSurface surface) {
108 | if (!mIsCompleted) {
109 | mIsCompleted = mRatio == 1;
110 | }
111 | if (mAnimator.isStopped()) {
112 | stop();
113 | }
114 | }
115 |
116 | private float getRadius(Vec pos) {
117 | return (float) Math.sqrt(pos.x() * pos.x() + pos.y() * pos.y());
118 | }
119 |
120 | private float getRadius(SurfaceModel model, int x, int y) {
121 | ReusableVec pos = VecPool.get(3);
122 | try {
123 | model.getPosition(x, y, pos);
124 | return (float) Math.sqrt(pos.x() * pos.x() + pos.y() * pos.y());
125 | } finally {
126 | pos.free();
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/launch/LaunchButtonMatrixUpdater.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.launch;
2 |
3 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
4 | import com.gplibs.magicsurfaceview.MagicSurface;
5 | import com.gplibs.magicsurfaceview.MagicSurfaceMatrixUpdater;
6 | import com.gplibs.magicsurfaceview.Vec;
7 |
8 | /**
9 | * STEP3~1
10 | */
11 | class LaunchButtonMatrixUpdater extends MagicSurfaceMatrixUpdater {
12 |
13 | private FloatValueAnimator mAnimator;
14 | private float mAnimValue = 0;
15 | private Vec mAxis = new Vec(3);
16 | private Vec mScale = new Vec(3);
17 |
18 | LaunchButtonMatrixUpdater(FloatValueAnimator animator, int group) {
19 | super(group);
20 | mAnimator = animator;
21 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
22 | @Override
23 | public void onAnimationUpdate(float value) {
24 | mAnimValue = value;
25 | // 通知框架,数据改变,可以调用 update 方法进行更新
26 | notifyChanged();
27 | }
28 |
29 | @Override
30 | public void onStop() {
31 | // 通知框架,数据改变,可以调用 update 方法进行更新
32 | notifyChanged();
33 | }
34 | });
35 | }
36 |
37 | // 在绘制第一帧之前调用 (可以在此方法里进行一些初始化操作)
38 | @Override
39 | protected void willStart(MagicSurface surface) {
40 | mAxis.setXYZ(-1, 0, 0);
41 | }
42 |
43 | // 在开始绘制后调用(绘制第一帧后调用,一般动画可以在此开始)
44 | @Override
45 | protected void didStart(MagicSurface surface) {
46 | mAnimator.start(false);
47 | }
48 |
49 | // 当调用Updater 的 stop() 方法之后,真正停止后会回调此方法
50 | @Override
51 | protected void didStop(MagicSurface surface) {
52 | }
53 |
54 | /**
55 | * 在此方法里进行矩阵变换
56 | *
57 | * @param offset offse为模型相对场景中心的坐标偏移量, 如果不进行 offset 位移, model 就会显示在场景中心;
58 | *
59 | * 当使用 View 构造 MagicSurface 时,
60 | * View中心位置 相对 MagicSurfaceView中心位置的坐标偏移量 在场景坐标系中的表现就是 offset。
61 | *
62 | * @param matrix 矩阵
63 | */
64 | @Override
65 | protected void updateMatrix(MagicSurface surface, Vec offset, float[] matrix) {
66 | if (mAnimValue > LaunchActivity.STEP3) {
67 | reset(matrix);
68 | float ratio = (mAnimValue - LaunchActivity.STEP3) / (1 - LaunchActivity.STEP3);
69 | float angle = 360 * (1 - ratio);
70 | offset.z(-surface.getModel().getHeight());
71 | // 平移 要放在 旋转操作 前
72 | translate(matrix, offset);
73 | rotate(matrix, mAxis, angle);
74 | mScale.setXYZ(ratio, ratio, ratio);
75 | scale(matrix, mScale);
76 | }
77 | if (mAnimator.isStopped()) {
78 | stop();
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/launch/LaunchButtonModelUpdater.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.launch;
2 |
3 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
4 | import com.gplibs.magicsurfaceview.MagicSurface;
5 | import com.gplibs.magicsurfaceview.MagicSurfaceModelUpdater;
6 | import com.gplibs.magicsurfaceview.Vec;
7 |
8 | class LaunchButtonModelUpdater extends MagicSurfaceModelUpdater {
9 |
10 | private FloatValueAnimator mAnimator;
11 | private float mAnimValue = 0;
12 |
13 | // 半径
14 | private float mR;
15 | // 周长
16 | private float mP;
17 | // 模型高度值相对周长对应的弧度值
18 | private float mAngle;
19 |
20 | LaunchButtonModelUpdater(FloatValueAnimator animator, int group) {
21 | super(group);
22 | mAnimator = animator;
23 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
24 | @Override
25 | public void onAnimationUpdate(float value) {
26 | mAnimValue = value;
27 | // 通知框架,数据改变,可以调用 update 方法进行更新
28 | notifyChanged();
29 | }
30 |
31 | @Override
32 | public void onStop() {
33 | // 通知框架,数据改变,可以调用 update 方法进行更新
34 | notifyChanged();
35 | }
36 | });
37 | }
38 |
39 | // 在绘制第一帧之前调用 (可以在此方法里进行一些初始化操作)
40 | @Override
41 | protected void willStart(MagicSurface surface) {
42 | mR = surface.getModel().getHeight();
43 | mP = 2 * (float) Math.PI * mR;
44 | mAngle = surface.getModel().getHeight() / mP * (float) Math.PI * 2;
45 | }
46 |
47 | // 在开始绘制后调用(绘制第一帧后调用,一般动画可以在此开始)
48 | @Override
49 | protected void didStart(MagicSurface surface) {
50 | mAnimator.start(false);
51 | }
52 |
53 | // 当调用Updater 的 stop() 方法之后,真正停止后会回调此方法
54 | @Override
55 | protected void didStop(MagicSurface surface) {
56 | mAnimator.stop();
57 | }
58 |
59 | @Override
60 | protected void updateBegin(MagicSurface surface) {
61 | }
62 |
63 | /**
64 | * 修改网格模型 r行, c列处 的坐标及颜色, 修改后的值存到 outPos 和 outColor
65 | * (只需要修改网格模型各行各列点及可,点与点之间的坐标和颜色由 openGL 自动进行插值计算完成)
66 | * 注:此方法执行频率非常高;一般不要有分配新的堆内存的逻辑,会频繁产生gc操作影响性能,可以使用全局变量或者ReusableVec、VecPool
67 | *
68 | * @param surface
69 | * @param r 行
70 | * @param c 列
71 | * @param outPos 默认值为 r行c列点包含偏移量的原始坐标, 计算完成后的新坐标要更新到此变量
72 | * @param outColor 默认值为 rgba(1,1,1,1), 计算完成后的新颜色要更新到此变量
73 | */
74 | @Override
75 | protected void updatePosition(MagicSurface surface, int r, int c, Vec outPos, Vec outColor) {
76 | if (mAnimValue > LaunchActivity.STEP3) {
77 | float ratio = (mAnimValue - LaunchActivity.STEP3) / (1 - LaunchActivity.STEP3);
78 | ratio *= ratio;
79 | float offsetAngle = ((float) Math.PI * 2 - mAngle) * (1 - ratio);
80 |
81 | surface.getModel().getPositionExcludeOffset(r, c, outPos);
82 |
83 | float ratioY = 1 - (surface.getModel().getHeight() / 2 + outPos.y()) / surface.getModel().getHeight();
84 | ratioY *= ratioY;
85 | float halfWidth = surface.getModel().getWidth() / 2;
86 | float offsetX = halfWidth * (1 - ratioY) * (1 - ratio);
87 | outPos.x(outPos.x() - offsetX * outPos.x() / halfWidth); // x 由从上小下大锥形 逐渐恢复原值。
88 | float offset = (outPos.y()) / surface.getModel().getHeight() * mP;
89 | float a = offset / mP * (mAngle + offsetAngle); // a 是逐渐减小的过程,直到mAngle, 曲面拉伸弧度也减小。
90 | outPos.y((float) Math.sin(a) * mR);
91 | outPos.z((float) Math.cos(a) * mR);
92 | }
93 | }
94 |
95 | @Override
96 | protected void updateEnd(MagicSurface surface) {
97 | if (mAnimValue > LaunchActivity.STEP3) {
98 | surface.getModel().updateModelNormal();
99 | surface.setVisible(true);
100 | }
101 | if (mAnimator.isStopped()) {
102 | stop();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/launch/LaunchSceneUpdater.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.launch;
2 |
3 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
4 | import com.gplibs.magicsurfaceview.MagicScene;
5 | import com.gplibs.magicsurfaceview.MagicSceneUpdater;
6 | import com.gplibs.magicsurfaceview.MagicSurface;
7 | import com.gplibs.magicsurfaceview.PointLight;
8 | import com.gplibs.magicsurfaceview.Vec;
9 |
10 | class LaunchSceneUpdater extends MagicSceneUpdater {
11 |
12 | private FloatValueAnimator mAnimator;
13 | private float mAnimValue = 0;
14 |
15 | private float mLightColor = 1.0f; // 灯光最亮颜色值
16 | private Vec mBeginPoint = new Vec(3); // 开始移动的坐标
17 | private Vec mCurrentPoint = new Vec(3); // 当前移动到的坐标
18 |
19 | LaunchSceneUpdater(FloatValueAnimator animator, int group) {
20 | super(group);
21 | mAnimator = animator;
22 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
23 | @Override
24 | public void onAnimationUpdate(float value) {
25 | mAnimValue = value;
26 | // 通知框架,数据改变,可以调用 update 方法进行更新
27 | notifyChanged();
28 | }
29 |
30 | @Override
31 | public void onStop() {
32 | // 通知框架,数据改变,可以调用 update 方法进行更新
33 | notifyChanged();
34 | }
35 | });
36 | }
37 |
38 | // 在绘制第一帧之前调用 (可以在此方法里进行一些初始化操作)
39 | @Override
40 | protected void willStart(MagicScene scene) {
41 | // 获取文本Surface; 文本Surface 是在构造MagicScene时第二个添加,所以可以通过 scene.getSurface(1) 获取.
42 | MagicSurface surface = scene.getSurface(1);
43 | surface.getModel().getPosition(0, 0, mBeginPoint);
44 | mBeginPoint.y(mBeginPoint.y() - surface.getModel().getHeight() / 2);
45 | mBeginPoint.z(0.14f);
46 |
47 | Vec pos = new Vec(3);
48 | scene.getCameraPos(pos);
49 | float y = mBeginPoint.y() - pos.y();
50 | mBeginPoint.y(mBeginPoint.y() + 0.14f * y / pos.z());
51 | }
52 |
53 | // 在开始绘制后调用(绘制第一帧后调用,一般动画可以在此开始)
54 | @Override
55 | protected void didStart(MagicScene scene) {
56 | mAnimator.start(false);
57 | }
58 |
59 | // 当调用Updater 的 stop() 方法之后,真正停止后会回调此方法
60 | @Override
61 | protected void didStop(MagicScene scene) {
62 | mAnimator.stop();
63 | }
64 |
65 | // 更新环境光及灯光
66 | @Override
67 | protected void update(MagicScene scene, Vec outAmbientColor) {
68 | PointLight light = scene.getLight(0);
69 | if (mAnimValue < LaunchActivity.STEP1) {
70 | // 0~STEP1 不使用灯光
71 |
72 | if (light.isEnable()) {
73 | light.setEnable(false);
74 | }
75 | } else if (mAnimValue >= LaunchActivity.STEP1 && mAnimValue <= LaunchActivity.STEP2) {
76 | // STEP1~STEP2 灯光逐渐变亮
77 |
78 | if (!light.isEnable()) {
79 | light.setEnable(true);
80 | }
81 | float c = mLightColor * (mAnimValue - 0.2f) / 0.1f;
82 | light.setColor(c, c, c, 1.f);
83 | light.setPosition(mBeginPoint);
84 | } else if (mAnimValue < LaunchActivity.STEP3) {
85 | // STEP2~STEP3 移动灯光
86 |
87 | if (light.getColor().r() != mLightColor) {
88 | light.setColor(mLightColor, mLightColor, mLightColor, 1.f);
89 | }
90 | float r = (mAnimValue - LaunchActivity.STEP2) / (LaunchActivity.STEP3 - LaunchActivity.STEP2);
91 | mCurrentPoint.copy(mBeginPoint);
92 | mCurrentPoint.x(mCurrentPoint.x() + r * scene.getWidth());
93 | light.setPosition(mCurrentPoint);
94 | } else if (mAnimValue >= LaunchActivity.STEP3) {
95 | // STEP3~1 灯光变暗,环境光变亮
96 |
97 | float r = (mAnimValue - LaunchActivity.STEP3) / (1 - LaunchActivity.STEP3);
98 | outAmbientColor.setRGBA(r, r, r, 1.f);
99 | float c = mLightColor * (1 - r);
100 | light.setColor(c, c, c, 1.f);
101 | }
102 |
103 | // 动画停止时 调用stop()停止Updater
104 | if (mAnimator.isStopped()) {
105 | stop();
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/launch/LaunchTextModelUpdater.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.launch;
2 |
3 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
4 | import com.gplibs.magicsurfaceview.MagicSurface;
5 | import com.gplibs.magicsurfaceview.MagicSurfaceModelUpdater;
6 | import com.gplibs.magicsurfaceview.Vec;
7 |
8 | /**
9 | * STEP2~STEP3
10 | */
11 | class LaunchTextModelUpdater extends MagicSurfaceModelUpdater {
12 |
13 | private FloatValueAnimator mAnimator;
14 | private float mAnimValue = 0;
15 | private float mRatio = 0;
16 | private boolean mIsCompleted;
17 | private float mLeft;
18 |
19 | LaunchTextModelUpdater(FloatValueAnimator animator, int group) {
20 | super(group);
21 | mAnimator = animator;
22 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
23 | @Override
24 | public void onAnimationUpdate(float value) {
25 | mAnimValue = value;
26 | // 通知框架,数据改变,可以调用 update 方法进行更新
27 | notifyChanged();
28 | }
29 |
30 | @Override
31 | public void onStop() {
32 | // 通知框架,数据改变,可以调用 update 方法进行更新
33 | notifyChanged();
34 | }
35 | });
36 | }
37 |
38 | // 在绘制第一帧之前调用 (可以在此方法里进行一些初始化操作)
39 | @Override
40 | protected void willStart(MagicSurface surface) {
41 | Vec pos = new Vec(3);
42 | surface.getModel().getPosition(0, 0, pos);
43 | mLeft = pos.x();
44 | }
45 |
46 | // 在开始绘制后调用(绘制第一帧后调用,一般动画可以在此开始)
47 | @Override
48 | protected void didStart(MagicSurface surface) {
49 | mAnimator.start(false);
50 | }
51 |
52 | // 当调用Updater 的 stop() 方法之后,真正停止后会回调此方法
53 | @Override
54 | protected void didStop(MagicSurface surface) {
55 | mAnimator.stop();
56 | }
57 |
58 | @Override
59 | protected void updateBegin(MagicSurface surface) {
60 | }
61 |
62 | /**
63 | * 修改网格模型 r行, c列处 的坐标及颜色, 修改后的值存到 outPos 和 outColor
64 | * (只需要修改网格模型各行各列点及可,点与点之间的坐标和颜色由 openGL 自动进行插值计算完成)
65 | * 注:此方法执行频率非常高;一般不要有分配新的堆内存的逻辑,会频繁产生gc操作影响性能,可以使用全局变量或者ReusableVec、VecPool
66 | *
67 | * @param surface
68 | * @param r 行
69 | * @param c 列
70 | * @param outPos 默认值为 r行c列点包含偏移量的原始坐标, 计算完成后的新坐标要更新到此变量
71 | * @param outColor 默认值为 rgba(1,1,1,1), 计算完成后的新颜色要更新到此变量
72 | */
73 | @Override
74 | protected void updatePosition(MagicSurface surface, int r, int c, Vec outPos, Vec outColor) {
75 | if (mAnimValue > LaunchActivity.STEP2 && !mIsCompleted) {
76 | mRatio = (mAnimValue - LaunchActivity.STEP2) / (LaunchActivity.STEP3 - LaunchActivity.STEP2);
77 | if (mRatio > 1) {
78 | mRatio = 1;
79 | }
80 | float centerX = mLeft + mRatio * surface.getModel().getWidth();
81 | float offset = centerX - outPos.x();
82 | outColor.a(offset <= 0 ? 0 : 1);
83 | }
84 | }
85 |
86 | @Override
87 | protected void updateEnd(MagicSurface surface) {
88 | if(mAnimValue > LaunchActivity.STEP2 && !mIsCompleted) {
89 | surface.setVisible(true);
90 | }
91 | mIsCompleted = mRatio == 1;
92 | if (mAnimator.isStopped()) {
93 | stop();
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/updater/MacWindowAnimUpdater.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.updater;
2 |
3 | import com.gplibs.magic_surface_view_sample.common.Direction;
4 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
5 | import com.gplibs.magicsurfaceview.MagicSurface;
6 | import com.gplibs.magicsurfaceview.MagicSurfaceModelUpdater;
7 | import com.gplibs.magicsurfaceview.SurfaceModel;
8 | import com.gplibs.magicsurfaceview.Vec;
9 |
10 | /**
11 | * 模仿Mac窗口动画
12 | */
13 | public class MacWindowAnimUpdater extends MagicSurfaceModelUpdater {
14 |
15 | private final float MODIFY_TARGET_TOTAL_TIME = 0.1f; // 动画使用 1/10 的时间完成下端收缩或者展开。
16 |
17 | private FloatValueAnimator mAnimator;
18 | private float mAnimValue = 0;
19 |
20 | private float mStartChangeOffsetTime; // 开始移动位置的时间
21 | private boolean mIsHideAnim = true;
22 | private float mTarget;
23 | private int mDirection = Direction.BOTTOM;
24 |
25 | private Vec mToCenter = new Vec(3);
26 | private Vec mToBegin = new Vec(3);
27 | private Vec mToEnd = new Vec(3);
28 | private Vec mFromBegin = new Vec(3);
29 | private Vec mFromEnd = new Vec(3);
30 | private float mOffset;
31 | private boolean mIsVertical;
32 | private boolean mRangeOfSelf = false;
33 | private float mMoveLengthValue;
34 | private float mFromSize;
35 |
36 | public MacWindowAnimUpdater(boolean isHideAnim, int direction, float target, boolean rangeOfSelf) {
37 | super();
38 | mIsHideAnim = isHideAnim;
39 | mDirection = direction;
40 | mTarget = target;
41 | mRangeOfSelf = rangeOfSelf;
42 |
43 | mAnimator = new FloatValueAnimator(600);
44 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
45 | @Override
46 | public void onAnimationUpdate(float value) {
47 | mAnimValue = value;
48 | // 通知框架,数据改变,可以调用 update 方法进行更新
49 | notifyChanged();
50 | }
51 |
52 | @Override
53 | public void onStop() {
54 | // 通知框架,数据改变,可以调用 update 方法进行更新
55 | notifyChanged();
56 | }
57 | });
58 | }
59 |
60 | // 在绘制第一帧之前调用 (可以在此方法里进行一些初始化操作)
61 | @Override
62 | protected void willStart(MagicSurface surface) {
63 | SurfaceModel model = surface.getModel();
64 | switch (mDirection) {
65 | case Direction.LEFT:
66 | model.getPosition(0, model.getColLineCount() - 1, mFromBegin);
67 | model.getPosition(model.getRowLineCount() - 1, model.getColLineCount() - 1, mFromEnd);
68 | if (mRangeOfSelf) {
69 | surface.getPosition(0, mTarget, mToCenter);
70 | } else {
71 | surface.getScene().getPosition(0, mTarget, mToCenter);
72 | }
73 | break;
74 | case Direction.RIGHT:
75 | model.getPosition(0, 0, mFromBegin);
76 | model.getPosition(model.getRowLineCount() - 1, 0, mFromEnd);
77 | if (mRangeOfSelf) {
78 | surface.getPosition(1, mTarget, mToCenter);
79 | } else {
80 | surface.getScene().getPosition(1, mTarget, mToCenter);
81 | }
82 | break;
83 | case Direction.TOP:
84 | model.getPosition(model.getRowLineCount() - 1, 0, mFromBegin);
85 | model.getPosition(model.getRowLineCount() - 1, model.getColLineCount() - 1, mFromEnd);
86 | if (mRangeOfSelf) {
87 | surface.getPosition(mTarget, 0, mToCenter);
88 | } else {
89 | surface.getScene().getPosition(mTarget, 0, mToCenter);
90 | }
91 | break;
92 | case Direction.BOTTOM:
93 | model.getPosition(0, 0, mFromBegin);
94 | model.getPosition(0, model.getColLineCount() - 1, mFromEnd);
95 | if (mRangeOfSelf) {
96 | surface.getPosition(mTarget, 1, mToCenter);
97 | } else {
98 | surface.getScene().getPosition(mTarget, 1, mToCenter);
99 | }
100 | break;
101 | }
102 |
103 | mAnimValue = mIsHideAnim ? 0 : 1;
104 | mIsVertical = Direction.isVertical(mDirection);
105 | float h;
106 | if (mIsVertical) {
107 | h = model.getHeight();
108 | mFromSize = model.getWidth();
109 | mMoveLengthValue = mFromBegin.y() - mToCenter.y();
110 | } else {
111 | h = model.getWidth();
112 | mFromSize = model.getHeight();
113 | mMoveLengthValue = mFromBegin.x() - mToCenter.x();
114 | }
115 | float r = Math.abs(h / mMoveLengthValue);
116 | mStartChangeOffsetTime = r * r * MODIFY_TARGET_TOTAL_TIME;
117 | }
118 |
119 | // 在开始绘制后调用(绘制第一帧后调用,一般动画可以在此开始)
120 | @Override
121 | protected void didStart(MagicSurface surface) {
122 | mAnimator.start(!mIsHideAnim);
123 | }
124 |
125 | // 当调用Updater 的 stop() 方法之后,真正停止后会回调此方法
126 | @Override
127 | protected void didStop(MagicSurface surface) {
128 | mAnimator.stop();
129 | }
130 |
131 | @Override
132 | protected void updateBegin(MagicSurface surface) {
133 | updateTarget(surface);
134 | updateOffset();
135 | }
136 |
137 | /**
138 | * 修改网格模型 r行, c列处 的坐标及颜色, 修改后的值存到 outPos 和 outColor
139 | * (只需要修改网格模型各行各列点及可,点与点之间的坐标和颜色由 openGL 自动进行插值计算完成)
140 | * 注:此方法执行频率非常高;一般不要有分配新的堆内存的逻辑,会频繁产生gc操作影响性能,可以使用全局变量或者ReusableVec、VecPool
141 | *
142 | * @param surface
143 | * @param r 行
144 | * @param c 列
145 | * @param outPos 默认值为 r行c列点包含偏移量的原始坐标, 计算完成后的新坐标要更新到此变量
146 | * @param outColor 默认值为 rgba(1,1,1,1), 计算完成后的新颜色要更新到此变量
147 | */
148 | @Override
149 | protected void updatePosition(MagicSurface surface, int r, int c, Vec outPos, Vec outColor) {
150 | if (mIsVertical) {
151 | outPos.y(outPos.y() - mOffset);
152 | float y = Math.abs(outPos.y());
153 | float t = mRangeOfSelf ? surface.getHeight() / 2 : surface.getScene().getHeight() / 2;
154 | if (y > t) {
155 | outPos.y(mOffset > 0 ? -t : t);
156 | }
157 | } else {
158 | outPos.x(outPos.x() - mOffset);
159 | float x = Math.abs(outPos.x());
160 | float t = mRangeOfSelf ? surface.getWidth() / 2 : surface.getScene().getWidth() / 2;
161 | if (x > t) {
162 | outPos.x(mOffset > 0 ? -t : t);
163 | }
164 | }
165 | updatePosition(outPos, mFromBegin, mFromEnd, mToBegin, mToEnd);
166 | }
167 |
168 | @Override
169 | protected void updateEnd(MagicSurface surface) {
170 | if (mAnimator.isStopped()) {
171 | // 调用 stop 方法,通知框架开始停止此 updater, 停止后会调用 didStop 方法。
172 | stop();
173 | }
174 | }
175 |
176 | private void updateTarget(MagicSurface surface) {
177 | SurfaceModel model = surface.getModel();
178 |
179 | float r = MODIFY_TARGET_TOTAL_TIME - mAnimValue;
180 | if (r < 0) {
181 | r = 0;
182 | }
183 | r /= MODIFY_TARGET_TOTAL_TIME;
184 | float range = r * (mIsVertical ? model.getWidth() : model.getHeight());
185 | if (range < 0.02f) {
186 | range = 0.02f;
187 | }
188 |
189 | if (mIsVertical) {
190 | float modelCenterX = mFromBegin.x() + model.getWidth() / 2;
191 | float targetX = modelCenterX + (1 - r) * (mToCenter.x() - modelCenterX);
192 | mToBegin.setXY(targetX - range / 2, mToCenter.y());
193 | mToEnd.setXY(targetX + range / 2, mToCenter.y());
194 | } else {
195 | float modelCenterY = mFromBegin.y() - model.getHeight() / 2;
196 | float targetY = modelCenterY + (1 - r) * (mToCenter.y() - modelCenterY);
197 | mToBegin.setXY(mToCenter.x(), targetY + range / 2);
198 | mToEnd.setXY(mToCenter.x(), targetY - range / 2);
199 | }
200 | }
201 |
202 | private void updateOffset() {
203 | if (mAnimValue > mStartChangeOffsetTime) {
204 | float r = (mAnimValue - mStartChangeOffsetTime) / (1 - mStartChangeOffsetTime);
205 | mOffset = mMoveLengthValue * r;
206 | } else {
207 | mOffset = 0;
208 | }
209 | }
210 |
211 | private void updatePosition(
212 | Vec pos, Vec fromBegin, Vec fromEnd,
213 | Vec toBegin, Vec toEnd) {
214 | float coordBegin = getNewPos(pos, fromBegin, toBegin);
215 | float coordEnd = getNewPos(pos, fromEnd, toEnd);
216 | float r = mIsVertical ? ((pos.x() - fromBegin.x()) / mFromSize) : ((fromBegin.y() - pos.y()) / mFromSize);
217 | float coord = coordBegin + (coordEnd - coordBegin) * r;
218 | if (mIsVertical) {
219 | pos.x(coord);
220 | } else {
221 | pos.y(coord);
222 | }
223 | }
224 |
225 | private float getNewPos(Vec pos, Vec start, Vec end) {
226 | float halfRatio = 0.5f;
227 | float ratio;
228 | if (mIsVertical) {
229 | ratio = (pos.y() - start.y()) / (end.y() - start.y());
230 | } else {
231 | ratio = (pos.x() - start.x()) / (end.x() - start.x());
232 | }
233 | float half;
234 | if (mIsVertical) {
235 | half = (end.x() - start.x()) / 2;
236 | } else {
237 | half = (end.y() - start.y()) / 2;
238 | }
239 | float coord = (mIsVertical ? start.x() : start.y());
240 | if (ratio < halfRatio) {
241 | float r = ratio / halfRatio;
242 | coord += r * r * half;
243 | } else {
244 | float r = (1 - ratio) / (1 - halfRatio);
245 | coord += (2 - r * r) * half;
246 | }
247 | return coord;
248 | }
249 |
250 | }
251 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/updater/MultiScrapUpdater.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.updater;
2 |
3 | import com.gplibs.magic_surface_view_sample.common.AnimHelper;
4 | import com.gplibs.magic_surface_view_sample.common.Direction;
5 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
6 | import com.gplibs.magic_surface_view_sample.common.RandomNumber;
7 | import com.gplibs.magicsurfaceview.MagicMultiSurface;
8 | import com.gplibs.magicsurfaceview.MagicMultiSurfaceUpdater;
9 | import com.gplibs.magicsurfaceview.Vec;
10 |
11 | public class MultiScrapUpdater extends MagicMultiSurfaceUpdater {
12 |
13 | private final float ANIM_TIME = 0.5f;
14 |
15 | private FloatValueAnimator mAnimator = new FloatValueAnimator(1000);
16 | private AnimHelper mAnimHelper;
17 | private int mDirection;
18 | private boolean mIsHide;
19 | private boolean mIsVertical;
20 | private RandomNumber[] mRandoms;
21 | private RandomNumber mRandom;
22 | private Vec mAxis = new Vec(0.5f, 0.5f, 1);
23 |
24 | public MultiScrapUpdater(boolean isHide, int direction) {
25 | mIsHide = isHide;
26 | mDirection = direction;
27 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
28 | @Override
29 | public void onAnimationUpdate(float value) {
30 | mAnimHelper.update(value);
31 | notifyChanged();
32 | }
33 |
34 | @Override
35 | public void onStop() {
36 | notifyChanged();
37 | }
38 | });
39 | }
40 |
41 | @Override
42 | protected void willStart(MagicMultiSurface surface) {
43 | surface.getScene().setCameraZ(2.f);
44 | mAnimHelper = new AnimHelper(surface, mDirection, mIsHide);
45 | mIsVertical = Direction.isVertical(mDirection);
46 | int count = mIsVertical ? surface.getRows() : surface.getCols();
47 | float t = (1 - ANIM_TIME) / count;
48 | mRandoms = new RandomNumber[count];
49 | for (int i = 0; i < mRandoms.length; ++i) {
50 | int n = mIsVertical ? surface.getCols(): surface.getRows();
51 | float time = mAnimHelper.getStartAnimTime(i, mRandoms.length, false, 1 - ANIM_TIME - t);
52 | mRandoms[i] = new RandomNumber(n, time, time + t);
53 | }
54 | mRandom = new RandomNumber(surface.getRows() * surface.getCols(), 0, 1);
55 | }
56 |
57 | @Override
58 | protected void didStart(MagicMultiSurface surface) {
59 | mAnimator.start(!mIsHide);
60 | }
61 |
62 | @Override
63 | protected void didStop(MagicMultiSurface surface) {
64 |
65 | }
66 |
67 | @Override
68 | protected void updateBegin(MagicMultiSurface surface) {
69 |
70 | }
71 |
72 | @Override
73 | protected void update(MagicMultiSurface surface, int r, int c, float[] matrix, Vec offset, Vec color) {
74 | float startTime = mRandoms[mIsVertical ? r : c].get(mIsVertical ? c : r);
75 | float ratio = mAnimHelper.getAnimProgress(startTime, ANIM_TIME);
76 | float ratio1 = mRandom.get(r * surface.getCols() + c);
77 | color.a(1 - ratio);
78 | float angle = 360 * ratio1 * ratio;
79 | float d = ratio1 * mAnimHelper.getMoveDistance(AnimHelper.MOVE_TYPE_SCENE, startTime, ANIM_TIME);
80 | if (mIsVertical) {
81 | offset.y(offset.y() + d);
82 | offset.x(offset.x() + ratio1 * ratio * surface.getWidth());
83 | } else {
84 | offset.x(offset.x() + d);
85 | }
86 | offset.z(offset.z() + 0.5f * ratio1 * ratio);
87 | reset(matrix);
88 | translate(matrix, offset);
89 | rotate(matrix, mAxis, angle);
90 | }
91 |
92 | @Override
93 | protected void updateEnd(MagicMultiSurface surface) {
94 | if (mAnimator.isStopped()) {
95 | stop();
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/updater/MultiSlideUpdater.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.updater;
2 |
3 | import com.gplibs.magic_surface_view_sample.common.AnimHelper;
4 | import com.gplibs.magic_surface_view_sample.common.Direction;
5 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
6 | import com.gplibs.magicsurfaceview.MagicMultiSurface;
7 | import com.gplibs.magicsurfaceview.MagicMultiSurfaceUpdater;
8 | import com.gplibs.magicsurfaceview.Vec;
9 |
10 | public class MultiSlideUpdater extends MagicMultiSurfaceUpdater {
11 |
12 | private final float MOVING_TOTAL_TIME = 0.4f;
13 |
14 | private FloatValueAnimator mAnimator = new FloatValueAnimator(600);
15 | private boolean mIsHide;
16 | private boolean mIsVertical;
17 | private int mDirection;
18 | private AnimHelper mAnimHelper;
19 | private Vec mAxis;
20 |
21 | public MultiSlideUpdater(boolean isHide, int direction) {
22 | mIsHide = isHide;
23 | mDirection = direction;
24 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
25 | @Override
26 | public void onAnimationUpdate(float value) {
27 | mAnimHelper.update(value);
28 | notifyChanged();
29 | }
30 |
31 | @Override
32 | public void onStop() {
33 | notifyChanged();
34 | }
35 | });
36 | }
37 |
38 | @Override
39 | protected void willStart(MagicMultiSurface surface) {
40 | mIsVertical = Direction.isVertical(mDirection);
41 | mAnimHelper = new AnimHelper(surface, mDirection, mIsHide);
42 | mAxis = mIsVertical ? new Vec(0, 1, 0) : new Vec(1, 0, 0);
43 | }
44 |
45 | @Override
46 | protected void didStart(MagicMultiSurface surface) {
47 | mAnimator.start(!mIsHide);
48 | }
49 |
50 | @Override
51 | protected void didStop(MagicMultiSurface surface) {
52 |
53 | }
54 |
55 | @Override
56 | protected void updateBegin(MagicMultiSurface surface) {
57 |
58 | }
59 |
60 | @Override
61 | protected void update(MagicMultiSurface surface, int r, int c, float[] matrix, Vec offset, Vec color) {
62 | float startTime = mAnimHelper.getStartAnimTime(
63 | mIsVertical ? r : c,
64 | mIsVertical ? surface.getRows() : surface.getCols(),
65 | false, 1 - MOVING_TOTAL_TIME);
66 | float ratio = mAnimHelper.getAnimProgress(startTime, MOVING_TOTAL_TIME);
67 | float len = mAnimHelper.getMoveDistance(AnimHelper.MOVE_TYPE_SCENE, startTime, MOVING_TOTAL_TIME);
68 | reset(matrix);
69 | if (mIsVertical) {
70 | offset.y(offset.y() + len);
71 | } else {
72 | offset.x(offset.x() + len);
73 | }
74 | translate(matrix, offset);
75 | rotate(matrix, mAxis, 110 * ratio);
76 | color.a(1 - ratio);
77 | }
78 |
79 | @Override
80 | protected void updateEnd(MagicMultiSurface surface) {
81 | if (mAnimator.isStopped()) {
82 | stop();
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/updater/VortexAnimUpdater.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.updater;
2 |
3 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
4 | import com.gplibs.magicsurfaceview.MagicSurface;
5 | import com.gplibs.magicsurfaceview.MagicSurfaceModelUpdater;
6 | import com.gplibs.magicsurfaceview.ReusableVec;
7 | import com.gplibs.magicsurfaceview.SurfaceModel;
8 | import com.gplibs.magicsurfaceview.Vec;
9 | import com.gplibs.magicsurfaceview.VecPool;
10 |
11 | /**
12 | * 旋涡动画
13 | */
14 | public class VortexAnimUpdater extends MagicSurfaceModelUpdater {
15 |
16 | private FloatValueAnimator mAnimator;
17 | private float mAnimValue = 0;
18 |
19 | private boolean mIsHide;
20 |
21 | private float maxRadius;
22 | private float mRotateTime = 0.2f;
23 |
24 | public VortexAnimUpdater(boolean isHide) {
25 | mIsHide = isHide;
26 | mAnimValue = mIsHide ? 0 : 1;
27 |
28 | mAnimator = new FloatValueAnimator(600);
29 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
30 | @Override
31 | public void onAnimationUpdate(float value) {
32 | mAnimValue = value;
33 | // 通知框架,数据改变,可以调用 update 方法进行更新
34 | notifyChanged();
35 | }
36 |
37 | @Override
38 | public void onStop() {
39 | // 通知框架,数据改变,可以调用 update 方法进行更新
40 | notifyChanged();
41 | }
42 | });
43 | }
44 |
45 | // 在绘制第一帧之前调用 (可以在此方法里进行一些初始化操作)
46 | @Override
47 | protected void willStart(MagicSurface surface) {
48 | SurfaceModel model = surface.getModel();
49 | Vec topLeft = new Vec(3);
50 | model.getPosition(0, 0, topLeft);
51 | maxRadius = Math.max(
52 | getRadius(model, 0, 0),
53 | Math.max(
54 | getRadius(model, 0, 1),
55 | Math.max(getRadius(model, 1, 0), getRadius(model, 1, 1))
56 | )
57 | );
58 | }
59 |
60 | // 在开始绘制后调用(绘制第一帧后调用,一般动画可以在此开始)
61 | @Override
62 | protected void didStart(MagicSurface surface) {
63 | mAnimator.start(!mIsHide);
64 | }
65 |
66 | // 当调用Updater 的 stop() 方法之后,真正停止后会回调此方法
67 | @Override
68 | protected void didStop(MagicSurface surface) {
69 | mAnimator.stop();
70 | }
71 |
72 | @Override
73 | protected void updateBegin(MagicSurface surface) {
74 |
75 | }
76 |
77 | /**
78 | * 修改网格模型 r行, c列处 的坐标及颜色, 修改后的值存到 outPos 和 outColor
79 | * (只需要修改网格模型各行各列点及可,点与点之间的坐标和颜色由 openGL 自动进行插值计算完成)
80 | * 注:此方法执行频率非常高;一般不要有分配新的堆内存的逻辑,会频繁产生gc操作影响性能,可以使用全局变量或者ReusableVec、VecPool
81 | *
82 | * @param surface
83 | * @param r 行
84 | * @param c 列
85 | * @param outPos 默认值为 r行c列点包含偏移量的原始坐标, 计算完成后的新坐标要更新到此变量
86 | * @param outColor 默认值为 rgba(1,1,1,1), 计算完成后的新颜色要更新到此变量
87 | */
88 | @Override
89 | protected void updatePosition(MagicSurface surface, int r, int c, Vec outPos, Vec outColor) {
90 | float radius = (float) Math.sqrt(outPos.x() * outPos.x() + outPos.y() * outPos.y());
91 | float rTime = 1;
92 | if (mAnimValue <= mRotateTime) {
93 | rTime = mAnimValue / mRotateTime;
94 | } else {
95 | float offset = maxRadius * (mAnimValue - mRotateTime) / (1 - mRotateTime);
96 | float newRadius = radius - offset;
97 | if (newRadius < 0) {
98 | newRadius = 0;
99 | }
100 | updatePos(outPos, radius, newRadius);
101 | radius = newRadius;
102 | }
103 | float ratio = radius / maxRadius;
104 | float zOffset = (1 - ratio) * 2 * rTime;
105 | outPos.z(outPos.z() - zOffset * zOffset);
106 | updatePos(outPos, (float) Math.PI * 2 * rTime * (1 - ratio));
107 | }
108 |
109 | @Override
110 | protected void updateEnd(MagicSurface surface) {
111 | if (mAnimator.isStopped()) {
112 | stop();
113 | }
114 | }
115 |
116 | private void updatePos(Vec pos, float oldRadius, float newRadius) {
117 | if (newRadius == 0) {
118 | pos.setXY(0, 0);
119 | return;
120 | }
121 | float r = newRadius / oldRadius;
122 | pos.setXY(
123 | pos.x() * r,
124 | pos.y() * r
125 | );
126 | }
127 |
128 | private void updatePos(Vec pos, float angle) {
129 | if (pos.x() == 0 && pos.y() == 0) {
130 | return;
131 | }
132 |
133 | float r = (float) Math.sqrt(pos.x() * pos.x() + pos.y() * pos.y());
134 | float a0;
135 | int index = getIndex(pos);
136 | if (index < 0) {
137 | a0 = getA(pos);
138 | } else {
139 | a0 = (float) Math.asin(pos.x() / r);
140 | if (a0 > 0) {
141 | if (index > 0) {
142 | a0 = (float) Math.PI - a0;
143 | }
144 | } else {
145 | if (index == 3) {
146 | a0 = (float) Math.PI * 2 + a0;
147 | } else {
148 | a0 = (float) Math.PI - a0;
149 | }
150 | }
151 | }
152 | float a1 = a0 + angle;
153 |
154 | double x = Math.sin(a1) * r;
155 | double y = Math.sqrt((x / Math.sin(a1)) * (x / Math.sin(a1)) - x * x);
156 | pos.setXY((float) x, (float) y);
157 | updatePosWithIndex(pos, getNewIndex(a1));
158 | }
159 |
160 | private int getNewIndex(double angle) {
161 | return ((int) (angle / ((float) Math.PI / 2))) % 4;
162 | }
163 |
164 | private void updatePosWithIndex(Vec vec, int index) {
165 | switch (index) {
166 | case 1:
167 | case 2:
168 | vec.y(-vec.y());
169 | break;
170 | }
171 | }
172 |
173 | private int getIndex(Vec pos) {
174 | if (pos.x() > 0 && pos.y() > 0) {
175 | return 0;
176 | } else if (pos.x() > 0 && pos.y() < 0) {
177 | return 1;
178 | } else if (pos.x() < 0 && pos.y() < 0) {
179 | return 2;
180 | } else if (pos.x() < 0 && pos.y() > 0) {
181 | return 3;
182 | } else {
183 | return -1;
184 | }
185 | }
186 |
187 | private float getA(Vec pos) {
188 | if (pos.x() == 0) {
189 | if (pos.y() > 0) {
190 | return 0;
191 | } else {
192 | return (float) Math.PI;
193 | }
194 | } else {
195 | if (pos.x() > 0) {
196 | return (float) Math.PI / 2;
197 | } else {
198 | return (float) Math.PI * 3 / 2;
199 | }
200 | }
201 | }
202 |
203 | private float getRadius(SurfaceModel model, int x, int y) {
204 | ReusableVec pos = VecPool.get(3);
205 | try {
206 | model.getPosition(x, y, pos);
207 | return (float) Math.sqrt(pos.x() * pos.x() + pos.y() * pos.y());
208 | } finally {
209 | pos.free();
210 | }
211 | }
212 |
213 | }
214 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gplibs/magic_surface_view_sample/updater/WaveAnimUpdater.java:
--------------------------------------------------------------------------------
1 | package com.gplibs.magic_surface_view_sample.updater;
2 |
3 | import com.gplibs.magic_surface_view_sample.common.Direction;
4 | import com.gplibs.magic_surface_view_sample.common.FloatValueAnimator;
5 | import com.gplibs.magic_surface_view_sample.common.AnimHelper;
6 | import com.gplibs.magicsurfaceview.MagicSurface;
7 | import com.gplibs.magicsurfaceview.MagicSurfaceModelUpdater;
8 | import com.gplibs.magicsurfaceview.Vec;
9 |
10 | /**
11 | * WaveAnimUpdater 将 model 中的每个点按PI范围内正弦波移动。
12 | * 并在移动过程中修改透明度。
13 | */
14 | public class WaveAnimUpdater extends MagicSurfaceModelUpdater {
15 |
16 | // 每个点移动所需时间占整个动画时间的比例
17 | private final float MOVING_TIME = 0.3f;
18 |
19 | // 是否为隐藏动画
20 | private boolean mIsHide;
21 | // 动画方向
22 | private int mDirection;
23 |
24 | private FloatValueAnimator mAnimator;
25 | private AnimHelper mAnimHelper;
26 | private boolean mIsVertical;
27 | private boolean mRangeOfSelf;
28 |
29 | public WaveAnimUpdater(boolean isHide, int direction, boolean rangeOfSelf) {
30 | mIsHide = isHide;
31 | mDirection = direction;
32 | mRangeOfSelf = rangeOfSelf;
33 |
34 | mAnimator = new FloatValueAnimator(600);
35 | mAnimator.addListener(new FloatValueAnimator.FloatValueAnimatorListener() {
36 | @Override
37 | public void onAnimationUpdate(float value) {
38 | mAnimHelper.update(value);
39 | // 通知框架,数据改变,可以调用 update 方法进行更新
40 | notifyChanged();
41 | }
42 |
43 | @Override
44 | public void onStop() {
45 | // 通知框架,数据改变,可以调用 update 方法进行更新
46 | notifyChanged();
47 | }
48 | });
49 | }
50 |
51 | // 在绘制第一帧之前调用 (可以在此方法里进行一些初始化操作)
52 | @Override
53 | protected void willStart(MagicSurface surface) {
54 | mAnimHelper = new AnimHelper(surface, mDirection, mIsHide);
55 | mIsVertical = Direction.isVertical(mDirection);
56 | }
57 |
58 | // 在开始绘制后调用(绘制第一帧后调用,一般动画可以在此开始)
59 | @Override
60 | protected void didStart(MagicSurface surface) {
61 | mAnimator.start(!mIsHide);
62 | }
63 |
64 | // 当调用Updater 的 stop() 方法之后,真正停止后会回调此方法
65 | @Override
66 | protected void didStop(MagicSurface surface) {
67 | mAnimator.stop();
68 | }
69 |
70 | @Override
71 | protected void updateBegin(MagicSurface surface) {
72 |
73 | }
74 |
75 | /**
76 | * 修改网格模型 r行, c列处 的坐标及颜色, 修改后的值存到 outPos 和 outColor
77 | * (只需要修改网格模型各行各列点及可,点与点之间的坐标和颜色由 openGL 自动进行插值计算完成)
78 | * 注:此方法执行频率非常高;一般不要有分配新的堆内存的逻辑,会频繁产生gc操作影响性能,可以使用全局变量或者ReusableVec、VecPool
79 | *
80 | * @param surface
81 | * @param r 行
82 | * @param c 列
83 | * @param outPos 默认值为 r行c列点包含偏移量的原始坐标, 计算完成后的新坐标要更新到此变量
84 | * @param outColor 默认值为 rgba(1,1,1,1), 计算完成后的新颜色要更新到此变量
85 | */
86 | @Override
87 | protected void updatePosition(MagicSurface surface, int r, int c, Vec outPos, Vec outColor) {
88 | float startTime = mAnimHelper.getStartAnimTime(outPos, false, (1 - MOVING_TIME));
89 | float offset = mAnimHelper.getMoveDistance(mRangeOfSelf ? AnimHelper.MOVE_TYPE_SELF : AnimHelper.MOVE_TYPE_SCENE, startTime, MOVING_TIME);
90 | if (mIsVertical) {
91 | outPos.y(outPos.y() + offset);
92 | } else {
93 | outPos.x(outPos.x() + offset);
94 | }
95 | float ratio = mAnimHelper.getAnimProgress(startTime, MOVING_TIME);
96 | outPos.z((float) Math.sin(Math.PI * ratio) / 2);
97 | outColor.a(1 - ratio);
98 | }
99 |
100 | @Override
101 | protected void updateEnd(MagicSurface surface) {
102 | if (mAnimator.isStopped()) {
103 | // 调用 stop 方法,通知框架开始停止此 updater, 停止后会调用 didStop 方法。
104 | stop();
105 | }
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dark_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/surface_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_launch.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
32 |
33 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_light_sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
24 |
25 |
31 |
36 |
41 |
42 |
43 |
50 |
55 |
61 |
62 |
63 |
76 |
77 |
90 |
99 |
107 |
115 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_mac_window_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
23 |
24 |
36 |
37 |
45 |
51 |
52 |
53 |
61 |
67 |
68 |
69 |
77 |
83 |
84 |
85 |
93 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_magic.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
24 |
25 |
30 |
39 |
40 |
41 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
25 |
26 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_matrix_anim_sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
30 |
31 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_multi_fold_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_multi_scrap_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
23 |
24 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_multi_slide_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
27 |
28 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_vortex_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
35 |
36 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_wave_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
36 |
37 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gplibs/android-magic-surface-view-sample/81a8488b52f0702eac0dfcef64942fcedba1b247/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gplibs/android-magic-surface-view-sample/81a8488b52f0702eac0dfcef64942fcedba1b247/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gplibs/android-magic-surface-view-sample/81a8488b52f0702eac0dfcef64942fcedba1b247/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gplibs/android-magic-surface-view-sample/81a8488b52f0702eac0dfcef64942fcedba1b247/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gplibs/android-magic-surface-view-sample/81a8488b52f0702eac0dfcef64942fcedba1b247/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v19/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 |
5 | #303F9F
6 | #FF4081
7 | #00000000
8 | #FFF
9 | #EEE
10 | #DDD
11 | #CCC
12 | #BBB
13 | #333
14 | #666
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MSV
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
22 |
23 |
28 |
29 |
34 |
35 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.3.2'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/local.properties:
--------------------------------------------------------------------------------
1 | ## This file is automatically generated by Android Studio.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must *NOT* be checked into Version Control Systems,
5 | # as it contains information specific to your local configuration.
6 | #
7 | # Location of the SDK. This is only used by Gradle.
8 | # For customization when using a Version Control System, please read the
9 | # header note.
10 | #Sat May 27 00:38:31 CST 2017
11 | ndk.dir=/Users/guoping/Software/dev/IDEA/android-sdk/ndk-bundle
12 | sdk.dir=/Users/guoping/Software/dev/IDEA/android-sdk
13 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------