[android] Separated content frame aka menu from button lines frame

This commit is contained in:
Александр Зацепин 2020-04-15 20:52:41 +03:00 committed by yoksnod
parent 3281d74b9e
commit 6ce42258fd
5 changed files with 204 additions and 314 deletions

View file

@ -12,10 +12,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Space
android:id="@+id/animation_spacer"
android:layout_width="0dp"
android:layout_height="0dp"/>
<FrameLayout
android:id="@+id/line_frame"
@ -47,19 +43,4 @@
tools:layout_marginTop="60dp"/>
</FrameLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
tools:visibility="visible">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider"/>
<include
layout="@layout/menu_content"/>
</FrameLayout>
</LinearLayout>

View file

@ -871,7 +871,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (mIsTabletLayout)
{
mPanelAnimator = new PanelAnimator(this);
mPanelAnimator.registerListener(mMainMenu.getLeftAnimationTrackListener());
return;
}
}

View file

@ -1,12 +1,11 @@
package com.mapswithme.maps.widget.menu;
import android.animation.Animator;
import android.view.View;
import androidx.annotation.DimenRes;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.View;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.util.ThemeUtils;
@ -16,20 +15,11 @@ public abstract class BaseMenu
{
public static final int ANIMATION_DURATION = MwmApplication.get().getResources().getInteger(R.integer.anim_menu);
private boolean mIsOpen;
private boolean mAnimating;
final View mFrame;
final View mLineFrame;
final View mContentFrame;
private final ItemClickListener mItemClickListener;
int mContentHeight;
boolean mLayoutMeasured;
public interface Item
{
@IdRes int getViewId();
@ -40,21 +30,6 @@ public abstract class BaseMenu
void onItemClick(T item);
}
private class AnimationListener extends UiUtils.SimpleAnimatorListener
{
@Override
public void onAnimationStart(android.animation.Animator animation)
{
mAnimating = true;
}
@Override
public void onAnimationEnd(android.animation.Animator animation)
{
mAnimating = false;
}
}
View mapItem(final Item item, View frame)
{
View res = frame.findViewById(item.getViewId());
@ -85,33 +60,7 @@ public abstract class BaseMenu
procAfterCorrection.run();
}
void measureContent(@Nullable final Runnable procAfterMeasurement)
{
if (mLayoutMeasured)
return;
UiUtils.measureView(mContentFrame, new UiUtils.OnViewMeasuredListener()
{
@Override
public void onViewMeasured(int width, int height)
{
if (height != 0)
{
mContentHeight = height;
mLayoutMeasured = true;
UiUtils.hide(mContentFrame);
}
afterLayoutMeasured(procAfterMeasurement);
}
});
}
public void onResume(@Nullable Runnable procAfterMeasurement)
{
measureContent(procAfterMeasurement);
updateMarker();
}
public abstract void onResume(@Nullable Runnable procAfterMeasurement);
BaseMenu(@NonNull View frame, @NonNull ItemClickListener<? extends Item> itemClickListener)
{
@ -119,112 +68,24 @@ public abstract class BaseMenu
mItemClickListener = itemClickListener;
mLineFrame = mFrame.findViewById(R.id.line_frame);
mContentFrame = mFrame.findViewById(R.id.content_frame);
adjustTransparency();
}
public boolean isOpen()
{
return mIsOpen;
}
public abstract boolean isOpen();
public boolean isAnimating()
{
return mAnimating;
}
public abstract boolean isAnimating();
public boolean open(boolean animate)
{
if ((animate && mAnimating) || isOpen())
return false;
mIsOpen = true;
UiUtils.show(mContentFrame);
adjustCollapsedItems();
adjustTransparency();
updateMarker();
setToggleState(mIsOpen, animate);
if (!animate)
return true;
mFrame.setTranslationY(mContentHeight);
mFrame.animate()
.setDuration(ANIMATION_DURATION)
.translationY(0.0f)
.setListener(new AnimationListener())
.start();
return true;
}
public abstract boolean open(boolean animate);
public boolean close(boolean animate)
{
return close(animate, null);
}
public boolean close(boolean animate, @Nullable final Runnable onCloseListener)
{
if (mAnimating || !isOpen())
{
if (onCloseListener != null)
onCloseListener.run();
public abstract boolean close(boolean animate, @Nullable final Runnable onCloseListener);
return false;
}
mIsOpen = false;
adjustCollapsedItems();
setToggleState(mIsOpen, animate);
if (!animate)
{
UiUtils.hide(mContentFrame);
adjustTransparency();
updateMarker();
if (onCloseListener != null)
onCloseListener.run();
return true;
}
mFrame.animate()
.setDuration(ANIMATION_DURATION)
.translationY(mContentHeight)
.setListener(new AnimationListener()
{
@Override
public void onAnimationEnd(Animator animation)
{
super.onAnimationEnd(animation);
mFrame.setTranslationY(0.0f);
UiUtils.hide(mContentFrame);
adjustTransparency();
updateMarker();
if (onCloseListener != null)
onCloseListener.run();
}
}).start();
return true;
}
public void toggle(boolean animate)
{
if (mAnimating)
return;
boolean show = !isOpen();
if (show)
open(animate);
else
close(animate);
}
public abstract void toggle(boolean animate);
public void show(boolean show)
{
@ -239,7 +100,6 @@ public abstract class BaseMenu
return mFrame;
}
protected void adjustCollapsedItems() {}
protected void updateMarker() {}
protected void setToggleState(boolean open, boolean animate) {}

View file

@ -1,27 +1,21 @@
package com.mapswithme.maps.widget.menu;
import androidx.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapswithme.maps.ClickMenuDelegate;
import com.mapswithme.maps.MwmActivity;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.maps.downloader.MapManager;
import com.mapswithme.maps.downloader.UpdateInfo;
import com.mapswithme.maps.routing.RoutingController;
import com.mapswithme.util.Animations;
import com.mapswithme.util.Graphics;
import com.mapswithme.util.UiUtils;
import com.mapswithme.util.statistics.StatisticValueConverter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
public class MainMenu extends BaseMenu
{
@ -51,77 +45,12 @@ public class MainMenu extends BaseMenu
}
}
private static final String TAG_COLLAPSE = MwmApplication.get().getString(R.string.tag_menu_collapse);
private final int mButtonsWidth = UiUtils.dimen(R.dimen.menu_line_button_width);
private final int mPanelWidth = UiUtils.dimen(R.dimen.panel_width);
private final View mButtonsFrame;
private final View mRoutePlanFrame;
private final View mAnimationSpacer;
private final View mAnimationSymmetricalGap;
private final View mNewsMarker;
private final TextView mNewsCounter;
private boolean mCollapsed;
private final List<View> mCollapseViews = new ArrayList<>();
private final MenuToggle mToggle;
// Maps Item into button view placed on mContentFrame
private final Map<Item, View> mItemViews = new HashMap<>();
private final MwmActivity.LeftAnimationTrackListener mAnimationTrackListener = new MwmActivity.LeftAnimationTrackListener()
{
private float mSymmetricalGapScale;
@Override
public void onTrackStarted(boolean collapsed)
{
for (View v : mCollapseViews)
{
if (collapsed)
UiUtils.show(v);
v.setAlpha(collapsed ? 0.0f : 1.0f);
v.animate()
.alpha(collapsed ? 1.0f : 0.0f)
.start();
}
mToggle.setCollapsed(!collapsed, true);
mSymmetricalGapScale = (float) mButtonsWidth / mPanelWidth;
}
@Override
public void onTrackFinished(boolean collapsed)
{
mCollapsed = collapsed;
updateMarker();
if (collapsed)
for (View v : mCollapseViews)
UiUtils.hide(v);
}
@Override
public void onTrackLeftAnimation(float offset)
{
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) mAnimationSpacer.getLayoutParams();
lp.rightMargin = (int) offset;
mAnimationSpacer.setLayoutParams(lp);
if (mAnimationSymmetricalGap == null)
return;
lp = (ViewGroup.MarginLayoutParams) mAnimationSymmetricalGap.getLayoutParams();
lp.width = mButtonsWidth - (int) (mSymmetricalGapScale * offset);
mAnimationSymmetricalGap.setLayoutParams(lp);
}
};
public enum Item implements BaseMenu.Item, StatisticValueConverter<String>
{
MENU(R.id.toggle)
@ -273,41 +202,9 @@ public class MainMenu extends BaseMenu
}
}
@Override
View mapItem(BaseMenu.Item item, View frame)
{
View res = super.mapItem(item, frame);
if (res != null && TAG_COLLAPSE.equals(res.getTag()))
mCollapseViews.add(res);
return res;
}
private void mapItem(MainMenu.Item item)
{
mapItem(item, mButtonsFrame);
View view = mapItem(item, mContentFrame);
mItemViews.put(item, view);
if (view != null)
Graphics.tint((TextView)view);
}
@Override
protected void adjustCollapsedItems()
{
for (View v : mCollapseViews)
{
UiUtils.showIf(!mCollapsed, v);
v.setAlpha(mCollapsed ? 0.0f : 1.0f);
}
if (mAnimationSymmetricalGap == null)
return;
ViewGroup.LayoutParams lp = mAnimationSymmetricalGap.getLayoutParams();
lp.width = (mCollapsed ? 0 : mButtonsWidth);
mAnimationSymmetricalGap.setLayoutParams(lp);
}
@Override
@ -317,25 +214,59 @@ public class MainMenu extends BaseMenu
super.afterLayoutMeasured(procAfterCorrection);
}
@Override
public void onResume(@Nullable Runnable procAfterMeasurement)
{
updateMarker();
}
@Override
public boolean isOpen()
{
return false;
}
@Override
public boolean isAnimating()
{
return false;
}
@Override
public boolean open(boolean animate)
{
return false;
}
@Override
public boolean close(boolean animate, @Nullable Runnable onCloseListener)
{
if (onCloseListener != null)
onCloseListener.run();
return false;
}
@Override
public void toggle(boolean animate)
{
// Do nothing.
}
@Override
protected void updateMarker()
{
UpdateInfo info = MapManager.nativeGetUpdateInfo(null);
int count = (info == null ? 0 : info.filesCount);
boolean show = count > 0 && !isOpen() && (!mCollapsed || mCollapseViews.isEmpty());
boolean show = count > 0 && !isOpen();
UiUtils.showIf(show, mNewsMarker);
UiUtils.showIf(count > 0, mNewsCounter);
if (count > 0)
mNewsCounter.setText(String.valueOf(count));
}
@Override
protected void setToggleState(boolean open, boolean animate)
{
mToggle.setOpen(open, animate);
// Do nothing.
}
private void init()
@ -351,7 +282,6 @@ public class MainMenu extends BaseMenu
mapItem(Item.DOWNLOAD_MAPS);
mapItem(Item.SETTINGS);
adjustCollapsedItems();
setState(State.MENU, false, false);
}
@ -362,14 +292,10 @@ public class MainMenu extends BaseMenu
mButtonsFrame = mLineFrame.findViewById(R.id.buttons_frame);
mRoutePlanFrame = mLineFrame.findViewById(R.id.routing_plan_frame);
mAnimationSpacer = mFrame.findViewById(R.id.animation_spacer);
mAnimationSymmetricalGap = mButtonsFrame.findViewById(R.id.symmetrical_gap);
mToggle = new MenuToggle(mLineFrame, getHeightResId());
mapItem(Item.MENU, mLineFrame);
mNewsMarker = mButtonsFrame.findViewById(R.id.marker);
mNewsCounter = (TextView) mContentFrame.findViewById(R.id.counter);
init();
}
@ -385,14 +311,12 @@ public class MainMenu extends BaseMenu
if (state != State.NAVIGATION)
{
mToggle.show(state.showToggle());
mToggle.setCollapsed(mCollapsed, animateToggle);
mToggle.setOpen(false, false);
boolean expandContent;
boolean isRouting = state == State.ROUTE_PREPARE;
if (mRoutePlanFrame == null)
{
UiUtils.show(mButtonsFrame);
expandContent = false;
}
else
{
@ -400,24 +324,14 @@ public class MainMenu extends BaseMenu
UiUtils.showIf(isRouting, mRoutePlanFrame);
if (isRouting)
mToggle.hide();
expandContent = isRouting;
}
UiUtils.showIf(expandContent,
mItemViews.get(Item.SEARCH),
mItemViews.get(Item.BOOKMARKS));
setVisible(Item.ADD_PLACE, !isRouting);
}
if (mLayoutMeasured)
{
show(state != State.NAVIGATION && !isFullScreen);
UiUtils.showIf(state == State.MENU, mButtonsFrame);
UiUtils.showIf(state == State.ROUTE_PREPARE, mRoutePlanFrame);
mContentFrame.measure(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
mContentHeight = mContentFrame.getMeasuredHeight();
}
show(state != State.NAVIGATION && !isFullScreen);
UiUtils.showIf(state == State.MENU, mButtonsFrame);
UiUtils.showIf(state == State.ROUTE_PREPARE, mRoutePlanFrame);
}
public void setEnabled(Item item, boolean enable)
@ -435,14 +349,6 @@ public class MainMenu extends BaseMenu
final View itemInButtonsFrame = mButtonsFrame.findViewById(item.mViewId);
if (itemInButtonsFrame != null)
UiUtils.showIf(show, itemInButtonsFrame);
if (mItemViews.get(item) != null)
UiUtils.showIf(show, mItemViews.get(item));
}
public MwmActivity.LeftAnimationTrackListener getLeftAnimationTrackListener()
{
return mAnimationTrackListener;
}
public void showLineFrame(boolean show)

View file

@ -1,17 +1,18 @@
package com.mapswithme.maps.widget.menu;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapswithme.maps.Framework;
import com.mapswithme.maps.R;
import com.mapswithme.maps.sound.TtsPlayer;
import com.mapswithme.maps.maplayer.traffic.TrafficManager;
import com.mapswithme.maps.sound.TtsPlayer;
import com.mapswithme.maps.widget.RotateDrawable;
import com.mapswithme.util.Graphics;
import com.mapswithme.util.UiUtils;
@ -24,6 +25,16 @@ public class NavMenu extends BaseMenu
@NonNull
private final ImageView mTraffic;
final View mContentFrame;
int mContentHeight;
boolean mLayoutMeasured;
private boolean mIsOpen;
private boolean mAnimating;
public enum Item implements BaseMenu.Item
{
TOGGLE(R.id.toggle),
@ -46,10 +57,25 @@ public class NavMenu extends BaseMenu
}
}
private class AnimationListener extends UiUtils.SimpleAnimatorListener
{
@Override
public void onAnimationStart(android.animation.Animator animation)
{
mAnimating = true;
}
@Override
public void onAnimationEnd(android.animation.Animator animation)
{
mAnimating = false;
}
}
public NavMenu(View frame, ItemClickListener<Item> listener)
{
super(frame, listener);
mContentFrame = mFrame.findViewById(R.id.content_frame);
mToggleImage = new RotateDrawable(Graphics.tint(mFrame.getContext(), R.drawable.ic_menu_close, R.attr.iconTintLight));
ImageView toggle = (ImageView) mLineFrame.findViewById(R.id.toggle);
toggle.setImageDrawable(mToggleImage);
@ -69,10 +95,128 @@ public class NavMenu extends BaseMenu
@Override
public void onResume(@Nullable Runnable procAfterMeasurement)
{
super.onResume(procAfterMeasurement);
measureContent(procAfterMeasurement);
refresh();
}
public boolean isOpen()
{
return mIsOpen;
}
public boolean isAnimating()
{
return mAnimating;
}
public boolean open(boolean animate)
{
if ((animate && mAnimating) || isOpen())
return false;
mIsOpen = true;
UiUtils.show(mContentFrame);
adjustTransparency();
updateMarker();
setToggleState(mIsOpen, animate);
if (!animate)
return true;
mFrame.setTranslationY(mContentHeight);
mFrame.animate()
.setDuration(ANIMATION_DURATION)
.translationY(0.0f)
.setListener(new AnimationListener())
.start();
return true;
}
public boolean close(boolean animate, @Nullable final Runnable onCloseListener)
{
if (mAnimating || !isOpen())
{
if (onCloseListener != null)
onCloseListener.run();
return false;
}
mIsOpen = false;
setToggleState(mIsOpen, animate);
if (!animate)
{
UiUtils.hide(mContentFrame);
adjustTransparency();
updateMarker();
if (onCloseListener != null)
onCloseListener.run();
return true;
}
mFrame.animate()
.setDuration(ANIMATION_DURATION)
.translationY(mContentHeight)
.setListener(new AnimationListener()
{
@Override
public void onAnimationEnd(Animator animation)
{
super.onAnimationEnd(animation);
mFrame.setTranslationY(0.0f);
UiUtils.hide(mContentFrame);
adjustTransparency();
updateMarker();
if (onCloseListener != null)
onCloseListener.run();
}
}).start();
return true;
}
public void toggle(boolean animate)
{
if (mAnimating)
return;
boolean show = !isOpen();
if (show)
open(animate);
else
close(animate);
}
void measureContent(@Nullable final Runnable procAfterMeasurement)
{
if (mLayoutMeasured)
return;
UiUtils.measureView(mContentFrame, new UiUtils.OnViewMeasuredListener()
{
@Override
public void onViewMeasured(int width, int height)
{
if (height != 0)
{
mContentHeight = height;
mLayoutMeasured = true;
UiUtils.hide(mContentFrame);
}
afterLayoutMeasured(procAfterMeasurement);
}
});
}
public void refresh()
{
refreshTts();