Add touch interaction for the SplashFragment art

This commit is contained in:
Grishka 2023-04-12 19:20:23 +03:00
parent 0de227ab9c
commit 4ef18f1f4a
3 changed files with 104 additions and 23 deletions

View File

@ -9,8 +9,8 @@ android {
applicationId "org.joinmastodon.android"
minSdk 23
targetSdk 33
versionCode 52
versionName "1.2.1"
versionCode 53
versionName "1.2.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resConfigs "ar-rSA", "be-rBY", "bn-rBD", "bs-rBA", "ca-rES", "cs-rCZ", "da-rDK", "de-rDE", "el-rGR", "es-rES", "eu-rES", "fa-rIR", "fi-rFI", "fil-rPH", "fr-rFR", "ga-rIE", "gd-rGB", "gl-rES", "hi-rIN", "hr-rHR", "hu-rHU", "hy-rAM", "ig-rNG", "in-rID", "is-rIS", "it-rIT", "iw-rIL", "ja-rJP", "kab", "ko-rKR", "my-rMM", "nl-rNL", "no-rNO", "oc-rFR", "pl-rPL", "pt-rBR", "pt-rPT", "ro-rRO", "ru-rRU", "si-rLK", "sl-rSI", "sv-rSE", "th-rTH", "tr-rTR", "uk-rUA", "ur-rIN", "vi-rVN", "zh-rCN", "zh-rTW"
}

View File

@ -1,20 +1,13 @@
package org.joinmastodon.android.fragments;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.style.ReplacementSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.R;
@ -28,10 +21,7 @@ import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.SizeListenerFrameLayout;
import org.parceler.Parcels;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
@ -74,11 +64,12 @@ public class SplashFragment extends AppKitFragment{
artContainer=contentView.findViewById(R.id.art_container);
blueFill=contentView.findViewById(R.id.blue_fill);
greenFill=contentView.findViewById(R.id.green_fill);
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(contentView.findViewById(R.id.art_clouds), V.dp(-5), V.dp(5), V.dp(-5), V.dp(5)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(contentView.findViewById(R.id.art_right_hill), V.dp(-15), V.dp(25), V.dp(-10), V.dp(10)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(contentView.findViewById(R.id.art_left_hill), V.dp(-25), V.dp(15), V.dp(-15), V.dp(15)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(contentView.findViewById(R.id.art_center_hill), V.dp(-14), V.dp(14), V.dp(-5), V.dp(25)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(contentView.findViewById(R.id.art_plane_elephant), V.dp(-20), V.dp(12), V.dp(-20), V.dp(12)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(artClouds, V.dp(-5), V.dp(5), V.dp(-5), V.dp(5)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(artRightHill, V.dp(-15), V.dp(25), V.dp(-10), V.dp(10)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(artLeftHill, V.dp(-25), V.dp(15), V.dp(-15), V.dp(15)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(artCenterHill, V.dp(-14), V.dp(14), V.dp(-5), V.dp(25)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(artPlaneElephant, V.dp(-20), V.dp(12), V.dp(-20), V.dp(12)));
artContainer.setOnTouchListener(motionEffect);
contentView.setSizeListener(new SizeListenerFrameLayout.OnSizeChangedListener(){
@Override

View File

@ -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;