More onboarding updates
This commit is contained in:
parent
a1798b6666
commit
bcb3e217cd
|
@ -5,6 +5,7 @@ import android.graphics.Paint;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -19,6 +20,7 @@ import org.joinmastodon.android.model.Instance;
|
||||||
import org.joinmastodon.android.ui.DividerItemDecoration;
|
import org.joinmastodon.android.ui.DividerItemDecoration;
|
||||||
import org.joinmastodon.android.ui.OutlineProviders;
|
import org.joinmastodon.android.ui.OutlineProviders;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
import org.joinmastodon.android.utils.ElevationOnScrollListener;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
@ -42,6 +44,7 @@ import me.grishka.appkit.utils.BindableViewHolder;
|
||||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||||
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
|
import me.grishka.appkit.views.FragmentRootLinearLayout;
|
||||||
import me.grishka.appkit.views.UsableRecyclerView;
|
import me.grishka.appkit.views.UsableRecyclerView;
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
import okhttp3.Callback;
|
import okhttp3.Callback;
|
||||||
|
@ -58,6 +61,7 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
|
||||||
private ArrayList<Item> items=new ArrayList<>();
|
private ArrayList<Item> items=new ArrayList<>();
|
||||||
private Call currentRequest;
|
private Call currentRequest;
|
||||||
private ItemsAdapter itemsAdapter;
|
private ItemsAdapter itemsAdapter;
|
||||||
|
private ElevationOnScrollListener onScrollListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState){
|
public void onCreate(Bundle savedInstanceState){
|
||||||
|
@ -72,7 +76,7 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
|
||||||
setNavigationBarColor(UiUtils.getThemeColor(activity, R.attr.colorWindowBackground));
|
setNavigationBarColor(UiUtils.getThemeColor(activity, R.attr.colorWindowBackground));
|
||||||
instance=Parcels.unwrap(getArguments().getParcelable("instance"));
|
instance=Parcels.unwrap(getArguments().getParcelable("instance"));
|
||||||
|
|
||||||
items.add(new Item("Mastodon for Android Privacy Policy", "joinmastodon.org", "https://joinmastodon.org/android/privacy", "https://joinmastodon.org/favicon-32x32.png"));
|
items.add(new Item("Mastodon for Android Privacy Policy", getString(R.string.privacy_policy_explanation), "joinmastodon.org", "https://joinmastodon.org/android/privacy", "https://joinmastodon.org/favicon-32x32.png"));
|
||||||
loadServerPrivacyPolicy();
|
loadServerPrivacyPolicy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,18 +97,24 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
|
||||||
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
View headerView=inflater.inflate(R.layout.item_list_header_simple, list, false);
|
View headerView=inflater.inflate(R.layout.item_list_header_simple, list, false);
|
||||||
TextView text=headerView.findViewById(R.id.text);
|
TextView text=headerView.findViewById(R.id.text);
|
||||||
text.setText(R.string.privacy_policy_subtitle);
|
text.setText(getString(R.string.privacy_policy_subtitle, instance.uri));
|
||||||
|
|
||||||
adapter=new MergeRecyclerAdapter();
|
adapter=new MergeRecyclerAdapter();
|
||||||
adapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
|
adapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
|
||||||
adapter.addAdapter(itemsAdapter=new ItemsAdapter());
|
adapter.addAdapter(itemsAdapter=new ItemsAdapter());
|
||||||
list.setAdapter(adapter);
|
list.setAdapter(adapter);
|
||||||
list.addItemDecoration(new DividerItemDecoration(getActivity(), R.attr.colorM3SurfaceVariant, 1, 56, 0, DividerItemDecoration.NOT_FIRST));
|
|
||||||
|
|
||||||
btn=view.findViewById(R.id.btn_next);
|
btn=view.findViewById(R.id.btn_next);
|
||||||
btn.setOnClickListener(v->onButtonClick());
|
btn.setOnClickListener(v->onButtonClick());
|
||||||
buttonBar=view.findViewById(R.id.button_bar);
|
buttonBar=view.findViewById(R.id.button_bar);
|
||||||
|
|
||||||
|
Button backBtn=view.findViewById(R.id.btn_back);
|
||||||
|
backBtn.setText(getString(R.string.server_policy_disagree, instance.uri));
|
||||||
|
backBtn.setOnClickListener(v->{
|
||||||
|
setResult(false, null);
|
||||||
|
Nav.finish(this);
|
||||||
|
});
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,13 +123,17 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
||||||
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
||||||
|
list.addOnScrollListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onUpdateToolbar(){
|
protected void onUpdateToolbar(){
|
||||||
super.onUpdateToolbar();
|
super.onUpdateToolbar();
|
||||||
getToolbar().setBackground(null);
|
getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
|
||||||
getToolbar().setElevation(0);
|
getToolbar().setElevation(0);
|
||||||
|
if(onScrollListener!=null){
|
||||||
|
onScrollListener.setViews(buttonBar, getToolbar());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onButtonClick(){
|
protected void onButtonClick(){
|
||||||
|
@ -158,7 +172,7 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
|
||||||
if(!response.isSuccessful())
|
if(!response.isSuccessful())
|
||||||
return;
|
return;
|
||||||
Document doc=Jsoup.parse(Objects.requireNonNull(body).byteStream(), Objects.requireNonNull(body.contentType()).charset(StandardCharsets.UTF_8).name(), req.url().toString());
|
Document doc=Jsoup.parse(Objects.requireNonNull(body).byteStream(), Objects.requireNonNull(body.contentType()).charset(StandardCharsets.UTF_8).name(), req.url().toString());
|
||||||
final Item item=new Item(doc.title(), instance.uri, req.url().toString(), "https://"+instance.uri+"/favicon.ico");
|
final Item item=new Item(doc.title(), null, instance.uri, req.url().toString(), "https://"+instance.uri+"/favicon.ico");
|
||||||
Activity activity=getActivity();
|
Activity activity=getActivity();
|
||||||
if(activity!=null){
|
if(activity!=null){
|
||||||
activity.runOnUiThread(()->{
|
activity.runOnUiThread(()->{
|
||||||
|
@ -192,16 +206,23 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
|
||||||
|
|
||||||
private class ItemViewHolder extends BindableViewHolder<Item> implements UsableRecyclerView.Clickable{
|
private class ItemViewHolder extends BindableViewHolder<Item> implements UsableRecyclerView.Clickable{
|
||||||
private final TextView title;
|
private final TextView title;
|
||||||
|
private final TextView subtitle;
|
||||||
|
|
||||||
public ItemViewHolder(){
|
public ItemViewHolder(){
|
||||||
super(getActivity(), R.layout.item_privacy_policy_link, list);
|
super(getActivity(), R.layout.item_privacy_policy_link, list);
|
||||||
title=findViewById(R.id.title);
|
title=findViewById(R.id.title);
|
||||||
title.setPaintFlags(title.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
subtitle=findViewById(R.id.subtitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBind(Item item){
|
public void onBind(Item item){
|
||||||
title.setText(item.title);
|
title.setText(item.title);
|
||||||
|
if(TextUtils.isEmpty(item.subtitle)){
|
||||||
|
subtitle.setVisibility(View.GONE);
|
||||||
|
}else{
|
||||||
|
subtitle.setVisibility(View.VISIBLE);
|
||||||
|
subtitle.setText(item.subtitle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -211,10 +232,11 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Item{
|
private static class Item{
|
||||||
public String title, domain, url, faviconUrl;
|
public String title, subtitle, domain, url, faviconUrl;
|
||||||
|
|
||||||
public Item(String title, String domain, String url, String faviconUrl){
|
public Item(String title, String subtitle, String domain, String url, String faviconUrl){
|
||||||
this.title=title;
|
this.title=title;
|
||||||
|
this.subtitle=subtitle;
|
||||||
this.domain=domain;
|
this.domain=domain;
|
||||||
this.url=url;
|
this.url=url;
|
||||||
this.faviconUrl=faviconUrl;
|
this.faviconUrl=faviconUrl;
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
package org.joinmastodon.android.fragments.onboarding;
|
package org.joinmastodon.android.fragments.onboarding;
|
||||||
|
|
||||||
import android.animation.Animator;
|
|
||||||
import android.animation.AnimatorListenerAdapter;
|
|
||||||
import android.animation.AnimatorSet;
|
|
||||||
import android.animation.ObjectAnimator;
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.LayerDrawable;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -37,6 +31,7 @@ import org.joinmastodon.android.ui.BetterItemAnimator;
|
||||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
import org.joinmastodon.android.ui.views.FilterChipView;
|
import org.joinmastodon.android.ui.views.FilterChipView;
|
||||||
|
import org.joinmastodon.android.utils.ElevationOnScrollListener;
|
||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -56,7 +51,6 @@ import me.grishka.appkit.api.Callback;
|
||||||
import me.grishka.appkit.api.ErrorResponse;
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
import me.grishka.appkit.fragments.OnBackPressedListener;
|
import me.grishka.appkit.fragments.OnBackPressedListener;
|
||||||
import me.grishka.appkit.utils.BindableViewHolder;
|
import me.grishka.appkit.utils.BindableViewHolder;
|
||||||
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
|
||||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||||
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
|
@ -211,47 +205,7 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
|
||||||
setStatusBarColor(0);
|
setStatusBarColor(0);
|
||||||
topBar=view.findViewById(R.id.top_bar);
|
topBar=view.findViewById(R.id.top_bar);
|
||||||
|
|
||||||
LayerDrawable topBg=(LayerDrawable) topBar.getBackground().mutate();
|
list.addOnScrollListener(new ElevationOnScrollListener(null, topBar, buttonBar));
|
||||||
topBar.setBackground(topBg);
|
|
||||||
Drawable topOverlay=topBg.findDrawableByLayerId(R.id.color_overlay);
|
|
||||||
topOverlay.setAlpha(0);
|
|
||||||
|
|
||||||
LayerDrawable btmBg=(LayerDrawable) buttonBar.getBackground().mutate();
|
|
||||||
buttonBar.setBackground(btmBg);
|
|
||||||
Drawable btmOverlay=btmBg.findDrawableByLayerId(R.id.color_overlay);
|
|
||||||
btmOverlay.setAlpha(0);
|
|
||||||
|
|
||||||
list.addOnScrollListener(new RecyclerView.OnScrollListener(){
|
|
||||||
private boolean isAtTop=true;
|
|
||||||
private Animator currentPanelsAnim;
|
|
||||||
@Override
|
|
||||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){
|
|
||||||
boolean newAtTop=recyclerView.getChildCount()==0 || (recyclerView.getChildAdapterPosition(recyclerView.getChildAt(0))==0 && recyclerView.getChildAt(0).getTop()==recyclerView.getPaddingTop());
|
|
||||||
if(newAtTop!=isAtTop){
|
|
||||||
isAtTop=newAtTop;
|
|
||||||
if(currentPanelsAnim!=null)
|
|
||||||
currentPanelsAnim.cancel();
|
|
||||||
|
|
||||||
AnimatorSet set=new AnimatorSet();
|
|
||||||
set.playTogether(
|
|
||||||
ObjectAnimator.ofInt(topOverlay, "alpha", isAtTop ? 0 : 20),
|
|
||||||
ObjectAnimator.ofInt(btmOverlay, "alpha", isAtTop ? 0 : 20),
|
|
||||||
ObjectAnimator.ofFloat(topBar, View.TRANSLATION_Z, isAtTop ? 0 : V.dp(3)),
|
|
||||||
ObjectAnimator.ofFloat(buttonBar, View.TRANSLATION_Z, isAtTop ? 0 : V.dp(3))
|
|
||||||
);
|
|
||||||
set.setDuration(150);
|
|
||||||
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
|
||||||
set.addListener(new AnimatorListenerAdapter(){
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation){
|
|
||||||
currentPanelsAnim=null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
set.start();
|
|
||||||
currentPanelsAnim=set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
searchEdit=view.findViewById(R.id.search_edit);
|
searchEdit=view.findViewById(R.id.search_edit);
|
||||||
searchEdit.setOnEditorActionListener(this::onSearchEnterPressed);
|
searchEdit.setOnEditorActionListener(this::onSearchEnterPressed);
|
||||||
|
@ -684,4 +638,5 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
|
||||||
return (this==GENERAL)==isGeneral;
|
return (this==GENERAL)==isGeneral;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.joinmastodon.android.model.Instance;
|
||||||
import org.joinmastodon.android.ui.DividerItemDecoration;
|
import org.joinmastodon.android.ui.DividerItemDecoration;
|
||||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
import org.joinmastodon.android.utils.ElevationOnScrollListener;
|
||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -28,6 +29,7 @@ import me.grishka.appkit.utils.BindableViewHolder;
|
||||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||||
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
|
import me.grishka.appkit.views.FragmentRootLinearLayout;
|
||||||
import me.grishka.appkit.views.UsableRecyclerView;
|
import me.grishka.appkit.views.UsableRecyclerView;
|
||||||
|
|
||||||
public class InstanceRulesFragment extends ToolbarFragment{
|
public class InstanceRulesFragment extends ToolbarFragment{
|
||||||
|
@ -36,6 +38,9 @@ public class InstanceRulesFragment extends ToolbarFragment{
|
||||||
private Button btn;
|
private Button btn;
|
||||||
private View buttonBar;
|
private View buttonBar;
|
||||||
private Instance instance;
|
private Instance instance;
|
||||||
|
private ElevationOnScrollListener onScrollListener;
|
||||||
|
|
||||||
|
private static final int RULES_REQUEST=376;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState){
|
public void onCreate(Bundle savedInstanceState){
|
||||||
|
@ -81,19 +86,31 @@ public class InstanceRulesFragment extends ToolbarFragment{
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
||||||
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
||||||
|
list.addOnScrollListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onUpdateToolbar(){
|
protected void onUpdateToolbar(){
|
||||||
super.onUpdateToolbar();
|
super.onUpdateToolbar();
|
||||||
getToolbar().setBackground(null);
|
getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
|
||||||
getToolbar().setElevation(0);
|
getToolbar().setElevation(0);
|
||||||
|
if(onScrollListener!=null){
|
||||||
|
onScrollListener.setViews(buttonBar, getToolbar());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onButtonClick(){
|
protected void onButtonClick(){
|
||||||
Bundle args=new Bundle();
|
Bundle args=new Bundle();
|
||||||
args.putParcelable("instance", Parcels.wrap(instance));
|
args.putParcelable("instance", Parcels.wrap(instance));
|
||||||
Nav.go(getActivity(), GoogleMadeMeAddThisFragment.class, args);
|
Nav.goForResult(getActivity(), GoogleMadeMeAddThisFragment.class, args, RULES_REQUEST, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFragmentResult(int reqCode, boolean success, Bundle result){
|
||||||
|
super.onFragmentResult(reqCode, success, result);
|
||||||
|
if(reqCode==RULES_REQUEST && !success){
|
||||||
|
Nav.finish(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -601,4 +601,12 @@ public class UiUtils{
|
||||||
public static boolean isMIUI(){
|
public static boolean isMIUI(){
|
||||||
return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.code"));
|
return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.code"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int alphaBlendColors(int color1, int color2, float alpha){
|
||||||
|
float alpha0=1f-alpha;
|
||||||
|
int r=Math.round(((color1 >> 16) & 0xFF)*alpha0+((color2 >> 16) & 0xFF)*alpha);
|
||||||
|
int g=Math.round(((color1 >> 8) & 0xFF)*alpha0+((color2 >> 8) & 0xFF)*alpha);
|
||||||
|
int b=Math.round((color1 & 0xFF)*alpha0+(color2 & 0xFF)*alpha);
|
||||||
|
return 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
package org.joinmastodon.android.utils;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.LayerDrawable;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||||
|
import me.grishka.appkit.utils.V;
|
||||||
|
import me.grishka.appkit.views.FragmentRootLinearLayout;
|
||||||
|
|
||||||
|
public class ElevationOnScrollListener extends RecyclerView.OnScrollListener implements View.OnScrollChangeListener{
|
||||||
|
private boolean isAtTop;
|
||||||
|
private Animator currentPanelsAnim;
|
||||||
|
private View[] views;
|
||||||
|
private FragmentRootLinearLayout fragmentRootLayout;
|
||||||
|
|
||||||
|
public ElevationOnScrollListener(FragmentRootLinearLayout fragmentRootLayout, View... views){
|
||||||
|
isAtTop=true;
|
||||||
|
this.fragmentRootLayout=fragmentRootLayout;
|
||||||
|
this.views=views;
|
||||||
|
for(View v:views){
|
||||||
|
Drawable bg=v.getBackground().mutate();
|
||||||
|
v.setBackground(bg);
|
||||||
|
if(bg instanceof LayerDrawable ld){
|
||||||
|
Drawable overlay=ld.findDrawableByLayerId(R.id.color_overlay);
|
||||||
|
if(overlay!=null){
|
||||||
|
overlay.setAlpha(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViews(View... views){
|
||||||
|
List<View> oldViews=Arrays.asList(this.views);
|
||||||
|
this.views=views;
|
||||||
|
for(View v:views){
|
||||||
|
if(oldViews.contains(v))
|
||||||
|
continue;
|
||||||
|
Drawable bg=v.getBackground().mutate();
|
||||||
|
v.setBackground(bg);
|
||||||
|
if(bg instanceof LayerDrawable ld){
|
||||||
|
Drawable overlay=ld.findDrawableByLayerId(R.id.color_overlay);
|
||||||
|
if(overlay!=null){
|
||||||
|
overlay.setAlpha(isAtTop ? 0 : 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.setTranslationZ(isAtTop ? 0 : V.dp(3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){
|
||||||
|
boolean newAtTop=recyclerView.getChildCount()==0 || (recyclerView.getChildAdapterPosition(recyclerView.getChildAt(0))==0 && recyclerView.getChildAt(0).getTop()==recyclerView.getPaddingTop());
|
||||||
|
handleScroll(recyclerView.getContext(), newAtTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY){
|
||||||
|
handleScroll(v.getContext(), scrollY==0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleScroll(Context context, boolean newAtTop){
|
||||||
|
if(newAtTop!=isAtTop){
|
||||||
|
isAtTop=newAtTop;
|
||||||
|
if(currentPanelsAnim!=null)
|
||||||
|
currentPanelsAnim.cancel();
|
||||||
|
|
||||||
|
AnimatorSet set=new AnimatorSet();
|
||||||
|
ArrayList<Animator> anims=new ArrayList<>();
|
||||||
|
for(View v:views){
|
||||||
|
if(v.getBackground() instanceof LayerDrawable ld){
|
||||||
|
Drawable overlay=ld.findDrawableByLayerId(R.id.color_overlay);
|
||||||
|
if(overlay!=null){
|
||||||
|
anims.add(ObjectAnimator.ofInt(overlay, "alpha", isAtTop ? 0 : 20));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
anims.add(ObjectAnimator.ofFloat(v, View.TRANSLATION_Z, isAtTop ? 0 : V.dp(3)));
|
||||||
|
}
|
||||||
|
if(fragmentRootLayout!=null){
|
||||||
|
int color;
|
||||||
|
if(isAtTop){
|
||||||
|
color=UiUtils.getThemeColor(context, R.attr.colorM3Background);
|
||||||
|
}else{
|
||||||
|
color=UiUtils.alphaBlendColors(UiUtils.getThemeColor(context, R.attr.colorM3Background), UiUtils.getThemeColor(context, R.attr.colorM3Primary), 0.07843137f);
|
||||||
|
}
|
||||||
|
anims.add(ObjectAnimator.ofArgb(fragmentRootLayout, "statusBarColor", color));
|
||||||
|
}
|
||||||
|
set.playTogether(anims);
|
||||||
|
set.setDuration(150);
|
||||||
|
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||||
|
set.addListener(new AnimatorListenerAdapter(){
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation){
|
||||||
|
currentPanelsAnim=null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
set.start();
|
||||||
|
currentPanelsAnim=set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<me.grishka.appkit.views.FragmentRootLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
@ -11,6 +11,7 @@
|
||||||
android:layout_weight="1"/>
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:background="@drawable/bg_onboarding_panel"
|
||||||
android:id="@+id/button_bar"
|
android:id="@+id/button_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -40,4 +41,4 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</me.grishka.appkit.views.FragmentRootLinearLayout>
|
</LinearLayout>
|
|
@ -1,18 +1,39 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingTop="12dp"
|
android:paddingTop="12dp"
|
||||||
android:paddingEnd="24dp"
|
|
||||||
android:paddingBottom="12dp"
|
android:paddingBottom="12dp"
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:textSize="16sp"
|
android:paddingEnd="24dp">
|
||||||
android:textColor="?colorM3Primary"
|
|
||||||
android:drawableStart="@drawable/ic_outline_link_24"
|
<View
|
||||||
android:drawablePadding="16dp"
|
android:id="@+id/icon"
|
||||||
android:drawableTint="?colorM3Primary"
|
android:layout_width="24dp"
|
||||||
tools:text="Privacy Policy - example.social">
|
android:layout_height="24dp"
|
||||||
|
android:backgroundTint="?colorM3Primary"
|
||||||
|
android:background="@drawable/ic_outline_link_24"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toEndOf="@id/icon"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:textAppearance="@style/m3_body_large"
|
||||||
|
android:textColor="?colorM3Primary"
|
||||||
|
tools:text="Privacy Policy - example.social"/>
|
||||||
|
|
||||||
</TextView>
|
<TextView
|
||||||
|
android:id="@+id/subtitle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toEndOf="@id/icon"
|
||||||
|
android:layout_below="@id/title"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:textAppearance="@style/m3_body_medium"
|
||||||
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
|
tools:text="Privacy Policy - example.social"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -389,7 +389,7 @@
|
||||||
<string name="download_update">Download (%s)</string>
|
<string name="download_update">Download (%s)</string>
|
||||||
<string name="install_update">Install</string>
|
<string name="install_update">Install</string>
|
||||||
<string name="privacy_policy_title">Your Privacy</string>
|
<string name="privacy_policy_title">Your Privacy</string>
|
||||||
<string name="privacy_policy_subtitle">Although the Mastodon app does not collect any data, the server you sign up through may have a different policy. Take a minute to review and agree to the Mastodon app privacy policy and your server\'s privacy policy.</string>
|
<string name="privacy_policy_subtitle">Although the Mastodon app does not collect any data, the server you sign up through may have a different policy.\n\nIf you disagree with the policy for %s, you can go back and pick a different server.</string>
|
||||||
<string name="i_agree">I Agree</string>
|
<string name="i_agree">I Agree</string>
|
||||||
<string name="empty_list">This list is empty</string>
|
<string name="empty_list">This list is empty</string>
|
||||||
<string name="instance_signup_closed">This server does not accept new registrations.</string>
|
<string name="instance_signup_closed">This server does not accept new registrations.</string>
|
||||||
|
@ -429,4 +429,7 @@
|
||||||
<string name="popular_on_mastodon">Popular on Mastodon</string>
|
<string name="popular_on_mastodon">Popular on Mastodon</string>
|
||||||
<string name="follow_all">Follow all</string>
|
<string name="follow_all">Follow all</string>
|
||||||
<string name="server_rules_disagree">Disagree</string>
|
<string name="server_rules_disagree">Disagree</string>
|
||||||
|
<string name="privacy_policy_explanation">TL;DR: We don\'t collect or process anything.</string>
|
||||||
|
<!-- %s is server domain -->
|
||||||
|
<string name="server_policy_disagree">Disagree with %s</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue