mirror of
https://github.com/mastodon/mastodon-android.git
synced 2024-12-26 00:36:37 +01:00
Add touch interaction for the SplashFragment art
This commit is contained in:
parent
0de227ab9c
commit
4ef18f1f4a
@ -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"
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user