Add touch interaction for the SplashFragment art
This commit is contained in:
@@ -1,17 +1,25 @@
|
||||
package org.joinmastodon.android.ui;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class InterpolatingMotionEffect implements SensorEventListener{
|
||||
import androidx.dynamicanimation.animation.DynamicAnimation;
|
||||
import androidx.dynamicanimation.animation.FloatValueHolder;
|
||||
import androidx.dynamicanimation.animation.SpringAnimation;
|
||||
import androidx.dynamicanimation.animation.SpringForce;
|
||||
|
||||
public class InterpolatingMotionEffect implements SensorEventListener, View.OnTouchListener{
|
||||
|
||||
private SensorManager sm;
|
||||
private WindowManager wm;
|
||||
@@ -20,6 +28,34 @@ public class InterpolatingMotionEffect implements SensorEventListener{
|
||||
private Sensor accelerometer;
|
||||
private boolean accelerometerEnabled;
|
||||
private ArrayList<ViewEffect> views=new ArrayList<>();
|
||||
private float pitch, roll;
|
||||
private float touchDownX, touchDownY, touchAddX, touchAddY, touchAddLastAnimX, touchAddLastAnimY;
|
||||
private PathInterpolator touchInterpolator=new PathInterpolator(0.5f, 1f, 0.89f, 1f);
|
||||
private SpringAnimation touchSpringX, touchSpringY;
|
||||
private FloatValueHolder touchSpringXHolder=new FloatValueHolder(){
|
||||
@Override
|
||||
public float getValue(){
|
||||
return touchAddX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(float value){
|
||||
touchAddX=value;
|
||||
updateEffects();
|
||||
}
|
||||
};
|
||||
private FloatValueHolder touchSpringYHolder=new FloatValueHolder(){
|
||||
@Override
|
||||
public float getValue(){
|
||||
return touchAddY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(float value){
|
||||
touchAddY=value;
|
||||
updateEffects();
|
||||
}
|
||||
};
|
||||
|
||||
public InterpolatingMotionEffect(Context context){
|
||||
sm=context.getSystemService(SensorManager.class);
|
||||
@@ -50,8 +86,8 @@ public class InterpolatingMotionEffect implements SensorEventListener{
|
||||
float z=event.values[2]/SensorManager.GRAVITY_EARTH;
|
||||
|
||||
|
||||
float pitch=(float) (Math.atan2(x, Math.sqrt(y*y+z*z))/Math.PI*2.0);
|
||||
float roll=(float) (Math.atan2(y, Math.sqrt(x*x+z*z))/Math.PI*2.0);
|
||||
pitch=(float) (Math.atan2(x, Math.sqrt(y*y+z*z))/Math.PI*2.0);
|
||||
roll=(float) (Math.atan2(y, Math.sqrt(x*x+z*z))/Math.PI*2.0);
|
||||
|
||||
switch(rotation){
|
||||
case Surface.ROTATION_0:
|
||||
@@ -88,9 +124,7 @@ public class InterpolatingMotionEffect implements SensorEventListener{
|
||||
}else if(roll<-1f){
|
||||
roll=-2f-roll;
|
||||
}
|
||||
for(ViewEffect view:views){
|
||||
view.update(pitch, roll);
|
||||
}
|
||||
updateEffects();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,6 +144,62 @@ public class InterpolatingMotionEffect implements SensorEventListener{
|
||||
views.clear();
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent ev){
|
||||
switch(ev.getAction()){
|
||||
case MotionEvent.ACTION_DOWN -> {
|
||||
if(touchSpringX!=null){
|
||||
touchAddLastAnimX=touchAddX;
|
||||
touchSpringX.cancel();
|
||||
touchSpringX=null;
|
||||
}else{
|
||||
touchAddLastAnimX=0;
|
||||
}
|
||||
if(touchSpringY!=null){
|
||||
touchAddLastAnimY=touchAddY;
|
||||
touchSpringY.cancel();
|
||||
touchSpringY=null;
|
||||
}else{
|
||||
touchAddLastAnimY=0;
|
||||
}
|
||||
touchDownX=ev.getX();
|
||||
touchDownY=ev.getY();
|
||||
}
|
||||
case MotionEvent.ACTION_MOVE -> {
|
||||
touchAddX=touchInterpolator.getInterpolation(Math.min(1f, Math.abs((ev.getX()-touchDownX)/(v.getWidth()/2f))));
|
||||
touchAddY=touchInterpolator.getInterpolation(Math.min(1f, Math.abs((ev.getY()-touchDownY)/(v.getHeight()/2f))));
|
||||
if(ev.getX()>touchDownX)
|
||||
touchAddX=-touchAddX;
|
||||
if(ev.getY()<touchDownY)
|
||||
touchAddY=-touchAddY;
|
||||
touchAddX+=touchAddLastAnimX;
|
||||
touchAddY+=touchAddLastAnimY;
|
||||
updateEffects();
|
||||
}
|
||||
case MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
touchSpringX=new SpringAnimation(touchSpringXHolder, 0f);
|
||||
touchSpringX.setMinimumVisibleChange(0.01f);
|
||||
touchSpringX.getSpring().setStiffness(SpringForce.STIFFNESS_LOW).setDampingRatio(0.85f);
|
||||
touchSpringX.addEndListener((animation, canceled, value, velocity)->touchSpringX=null);
|
||||
touchSpringX.start();
|
||||
touchSpringY=new SpringAnimation(touchSpringYHolder, 0f);
|
||||
touchSpringY.setMinimumVisibleChange(0.01f);
|
||||
touchSpringY.getSpring().setStiffness(SpringForce.STIFFNESS_LOW).setDampingRatio(0.85f);
|
||||
touchSpringY.addEndListener((animation, canceled, value, velocity)->touchSpringY=null);
|
||||
touchSpringY.start();
|
||||
updateEffects();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateEffects(){
|
||||
for(ViewEffect view:views){
|
||||
view.update(Math.min(1f, Math.max(-1f, pitch+touchAddX)), Math.min(1f, Math.max(-1f, roll+touchAddY)));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ViewEffect{
|
||||
private View view;
|
||||
private float minX, maxX, minY, maxY;
|
||||
|
||||
Reference in New Issue
Block a user