This exercise TRY to simulate the effect on Android. The code for motion aftereffect generation is modified from http://en.wikipedia.org/wiki/File:Illusion_movie.ogg (c source code), with my optimization. But the effect seem not good! I test it on Nexus 7 tablet.
To see the illusions: Run the app on Android Tablet, and stare to the center of the image. After around one minute, look away (for example look to a face or to your hands). For few seconds everything you see will appear to distort. Or touch the motion picture on screen, it will stop and change to another ImageView.
![]() |
Motion AfterEffect (MAE) |
The main part is in MySurfaceView.java.
package com.example.androidsurfaceview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MySurfaceView extends SurfaceView {
private SurfaceHolder surfaceHolder;
private MyThread myThread;
MainActivity mainActivity;
int T;
static final float freq = 80;
public MySurfaceView(Context context) {
super(context);
init(context);
}
public MySurfaceView(Context context,
AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MySurfaceView(Context context,
AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context c){
mainActivity = (MainActivity)c;
T = 0;
myThread = new MyThread(this);
surfaceHolder = getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback(){
@Override
public void surfaceCreated(SurfaceHolder holder) {
myThread.setRunning(true);
myThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
myThread.setRunning(false);
while (retry) {
try {
myThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}});
}
protected void drawSomething(Canvas canvas) {
int sizex = getWidth();
int sizey = getHeight();
float divby_sizex_sq = 1.0f/((float)sizex * (float)sizex);
int[] data = new int[sizex * sizey];
int m;
T++;
if(T >= 1200){
T = 0;
}
float halfT = T * 0.5f;
for (int j=0;j<sizey;j++){
float y0 = j*2-sizey;
float y2_2 = y0 * y0 * divby_sizex_sq;
float absY = Math.abs(y0/(float)sizey);
float halfT_plus_absY = absY + halfT;
float halfT_neg_plus_absY = absY - halfT;
int j_multi_sizex = j*sizex;
for (int i=0;i<sizex;i++){
float x=(i*2-sizex)/(float)sizex;
//0.2 instead of 0.1 to have a bigger circle
if ((x*x + y2_2)<0.2){
m = (int) (Math.sin((halfT_plus_absY+Math.abs(x))*freq)*127.0+128) & 0xFF;
}else {
m = (int) (Math.sin((halfT_neg_plus_absY+Math.abs(x))*freq)*127.0+128) & 0xFF;
}
data[i+j_multi_sizex] = 0xFF000000
+ (m << 16)
+ (m << 8)
+ m;
}
}
Bitmap bm = Bitmap.createBitmap(data, sizex, sizey, Bitmap.Config.ARGB_8888);
canvas.drawBitmap(bm, 0, 0, null);
}
}
MyThread.java
package com.example.androidsurfaceview;
import android.graphics.Canvas;
public class MyThread extends Thread {
MySurfaceView myView;
private boolean running = false;
public MyThread(MySurfaceView view) {
myView = view;
}
public void setRunning(boolean run) {
running = run;
}
@Override
public void run() {
while(running){
Canvas canvas = myView.getHolder().lockCanvas();
if(canvas != null){
synchronized (myView.getHolder()) {
myView.drawSomething(canvas);
}
myView.getHolder().unlockCanvasAndPost(canvas);
}
/*
try {
sleep(30);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
}
}
/res/layout/activity_main.xml, where @drawable/android_er is a 640x480 .png in /res/drawable/ folder.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/background_dark"
tools:context="com.example.androidsurfaceview.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<FrameLayout
android:layout_width="640dp"
android:layout_height="480dp"
android:layout_gravity="center">
<com.example.androidsurfaceview.MySurfaceView
android:id="@+id/myview"
android:layout_width="640dp"
android:layout_height="480dp"
android:layout_gravity="center" />
<ImageView
android:id="@+id/imageicon"
android:layout_width="640dp"
android:layout_height="480dp"
android:layout_gravity="center"
android:src="@drawable/android_er"
android:visibility="invisible"/>
</FrameLayout>
</LinearLayout>
MainActivity.java. The Motion graph will run when the app start. When user touch on it, it will show the ImageView of "@drawable/android_er".
package com.example.androidsurfaceview;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
public class MainActivity extends Activity {
ImageView imageIcon;
MySurfaceView mySurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySurfaceView = (MySurfaceView)findViewById(R.id.myview);
imageIcon = (ImageView)findViewById(R.id.imageicon);
mySurfaceView.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
imageIcon.setVisibility(View.VISIBLE);
mySurfaceView.setVisibility(View.INVISIBLE);
}});
}
}
Modify AndroidManifest.xml to force the app run in landscape mode.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidsurfaceview"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidsurfaceview.MainActivity"
android:label="@string/app_name"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Download and try the APK.
No comments:
Post a Comment