mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-31 04:16:30 +00:00
Apply better coordinatorlayout animation and RTL support.
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
package org.thoughtcrime.securesms.groups.ui.creategroup;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public final class GroupSettingsCoordinatorLayoutBehavior extends CoordinatorLayout.Behavior<View> {
|
||||
|
||||
private static final Interpolator INTERPOLATOR = new DecelerateInterpolator();
|
||||
|
||||
private final ViewRef avatarTargetRef = new ViewRef(R.id.avatar_target);
|
||||
private final ViewRef groupNameRef = new ViewRef(R.id.group_name);
|
||||
private final ViewRef groupNameTargetRef = new ViewRef(R.id.group_name_target);
|
||||
private final Rect targetRect = new Rect();
|
||||
private final Rect childRect = new Rect();
|
||||
|
||||
public GroupSettingsCoordinatorLayoutBehavior(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
|
||||
return dependency instanceof AppBarLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
|
||||
AppBarLayout appBarLayout = (AppBarLayout) dependency;
|
||||
int range = appBarLayout.getTotalScrollRange();
|
||||
float factor = INTERPOLATOR.getInterpolation(-appBarLayout.getY() / range);
|
||||
|
||||
updateAvatarPositionAndScale(parent, child, factor);
|
||||
updateNamePosition(parent, factor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateAvatarPositionAndScale(@NonNull CoordinatorLayout parent, @NonNull View child, float factor) {
|
||||
View target = avatarTargetRef.require(parent);
|
||||
|
||||
targetRect.set(target.getLeft(), target.getTop(), target.getRight(), target.getBottom());
|
||||
childRect.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom());
|
||||
|
||||
float widthScale = 1f - (1f - (targetRect.width() / (float) childRect.width())) * factor;
|
||||
float heightScale = 1f - (1f - (targetRect.height() / (float) childRect.height())) * factor;
|
||||
|
||||
float superimposedLeft = childRect.left + (childRect.width() - targetRect.width()) / 2f;
|
||||
float superimposedTop = childRect.top + (childRect.height() - targetRect.height()) / 2f;
|
||||
|
||||
float xTranslation = (targetRect.left - superimposedLeft) * factor;
|
||||
float yTranslation = (targetRect.top - superimposedTop) * factor;
|
||||
|
||||
child.setScaleX(widthScale);
|
||||
child.setScaleY(heightScale);
|
||||
child.setTranslationX(xTranslation);
|
||||
child.setTranslationY(yTranslation);
|
||||
}
|
||||
|
||||
private void updateNamePosition(@NonNull CoordinatorLayout parent, float factor) {
|
||||
TextView child = (TextView) groupNameRef.require(parent);
|
||||
View target = groupNameTargetRef.require(parent);
|
||||
|
||||
targetRect.set(target.getLeft(), target.getTop(), target.getRight(), target.getBottom());
|
||||
childRect.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom());
|
||||
|
||||
if (child.getMaxWidth() != targetRect.width()) {
|
||||
child.setMaxWidth(targetRect.width());
|
||||
}
|
||||
|
||||
float deltaTop = targetRect.top - childRect.top;
|
||||
float deltaStart = getStart(parent, targetRect) - getStart(parent, childRect);
|
||||
|
||||
float yTranslation = deltaTop * factor;
|
||||
float xTranslation = deltaStart * factor;
|
||||
|
||||
child.setTranslationY(yTranslation);
|
||||
child.setTranslationX(xTranslation);
|
||||
}
|
||||
|
||||
private static int getStart(@NonNull CoordinatorLayout parent, @NonNull Rect rect) {
|
||||
return parent.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR ? rect.left : rect.right;
|
||||
}
|
||||
|
||||
private static final class ViewRef {
|
||||
|
||||
private WeakReference<View> ref = new WeakReference<>(null);
|
||||
|
||||
private final @IdRes int idRes;
|
||||
|
||||
private ViewRef(@IdRes int idRes) {
|
||||
this.idRes = idRes;
|
||||
}
|
||||
|
||||
private @NonNull View require(@NonNull View parent) {
|
||||
View view = ref.get();
|
||||
|
||||
if (view == null) {
|
||||
view = getChildOrThrow(parent, idRes);
|
||||
ref = new WeakReference<>(view);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private static @NonNull View getChildOrThrow(@NonNull View parent, @IdRes int id) {
|
||||
View child = parent.findViewById(id);
|
||||
|
||||
if (child == null) {
|
||||
throw new AssertionError("Can't find view with ID " + R.id.avatar_target);
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,7 @@ public class ManageGroupFragment extends Fragment {
|
||||
private View pendingMembersRow;
|
||||
private TextView pendingMembersCount;
|
||||
private Toolbar toolbar;
|
||||
private TextView groupName;
|
||||
private TextView memberCountUnderAvatar;
|
||||
private TextView memberCountAboveList;
|
||||
private AvatarImageView avatar;
|
||||
@@ -115,6 +116,7 @@ public class ManageGroupFragment extends Fragment {
|
||||
|
||||
avatar = view.findViewById(R.id.group_avatar);
|
||||
toolbar = view.findViewById(R.id.toolbar);
|
||||
groupName = view.findViewById(R.id.group_name);
|
||||
memberCountUnderAvatar = view.findViewById(R.id.member_count);
|
||||
memberCountAboveList = view.findViewById(R.id.member_count_2);
|
||||
groupMemberList = view.findViewById(R.id.group_members);
|
||||
@@ -185,7 +187,7 @@ public class ManageGroupFragment extends Fragment {
|
||||
toolbar.inflateMenu(R.menu.manage_group_fragment);
|
||||
|
||||
viewModel.getCanEditGroupAttributes().observe(getViewLifecycleOwner(), canEdit -> toolbar.getMenu().findItem(R.id.action_edit).setVisible(canEdit));
|
||||
viewModel.getTitle().observe(getViewLifecycleOwner(), toolbar::setTitle);
|
||||
viewModel.getTitle().observe(getViewLifecycleOwner(), groupName::setText);
|
||||
viewModel.getMemberCountSummary().observe(getViewLifecycleOwner(), memberCountUnderAvatar::setText);
|
||||
viewModel.getFullMemberCountSummary().observe(getViewLifecycleOwner(), memberCountAboveList::setText);
|
||||
viewModel.getGroupRecipient().observe(getViewLifecycleOwner(), groupRecipient -> {
|
||||
|
||||
Reference in New Issue
Block a user