Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUi.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUi.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUi.java |
| index 09428c07607022ac3b53855c70553f103e64cdfe..18eb3cde70d715d6263e9d8362e690a776c837d5 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUi.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUi.java |
| @@ -4,25 +4,37 @@ |
| package org.chromium.chrome.browser.contextmenu; |
| +import android.app.ActionBar.LayoutParams; |
| import android.app.Activity; |
| import android.app.Dialog; |
| import android.content.DialogInterface; |
| import android.content.res.Resources; |
| import android.graphics.Bitmap; |
| import android.graphics.Canvas; |
| +import android.graphics.Color; |
| import android.graphics.Shader; |
| import android.graphics.drawable.BitmapDrawable; |
| +import android.graphics.drawable.ColorDrawable; |
| import android.graphics.drawable.Drawable; |
| import android.support.design.widget.TabLayout; |
| import android.support.v4.view.ViewPager; |
| +import android.support.v4.view.animation.LinearOutSlowInInterpolator; |
| import android.support.v7.app.AlertDialog; |
| import android.text.TextUtils; |
| import android.util.Pair; |
| +import android.view.Gravity; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| +import android.view.View.OnClickListener; |
| +import android.view.View.OnLayoutChangeListener; |
| import android.view.ViewGroup; |
| +import android.view.Window; |
| +import android.view.animation.Animation; |
| +import android.view.animation.Animation.AnimationListener; |
| +import android.view.animation.ScaleAnimation; |
| import android.widget.AdapterView; |
| import android.widget.BaseAdapter; |
| +import android.widget.FrameLayout; |
| import android.widget.ImageView; |
| import android.widget.ListView; |
| import android.widget.TextView; |
| @@ -31,6 +43,8 @@ import org.chromium.base.ApiCompatibilityUtils; |
| import org.chromium.base.Callback; |
| import org.chromium.base.VisibleForTesting; |
| import org.chromium.chrome.R; |
| +import org.chromium.chrome.browser.widget.AlwaysDismissedDialog; |
| +import org.chromium.content.browser.ContentViewCore; |
| import java.util.ArrayList; |
| import java.util.List; |
| @@ -44,6 +58,14 @@ public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl |
| private int mMenuItemHeight; |
| private ImageView mHeaderImageView; |
| private Runnable mOnShareItemClicked; |
| + private View mPagerView; |
| + |
| + private float mContextMenuSourceX; |
| + private float mContextMenuSourceY; |
| + private int mContextMenuLocationOnScreen; |
| + private int mContextMenuHeight = -1; |
| + private int mContextMenuWidth; |
| + private ContentViewCore mContentViewCore; |
| public TabularContextMenuUi(Runnable onShareItemClicked) { |
| mOnShareItemClicked = onShareItemClicked; |
| @@ -56,9 +78,6 @@ public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl |
| mCallback = onItemClicked; |
| mDialog = createDialog(activity, params, items); |
| - mDialog.getWindow().setBackgroundDrawable(ApiCompatibilityUtils.getDrawable( |
| - activity.getResources(), R.drawable.white_with_rounded_corners)); |
| - |
| mDialog.setOnShowListener(new DialogInterface.OnShowListener() { |
| @Override |
| public void onShow(DialogInterface dialogInterface) { |
| @@ -73,7 +92,27 @@ public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl |
| } |
| }); |
| + Window dialogWindow = mDialog.getWindow(); |
| + dialogWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); |
| + dialogWindow.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); |
| + |
| + float density = Resources.getSystem().getDisplayMetrics().density; |
| + final float touchPointX = params.getX() * density; |
| + final float touchPointY = params.getY() * density; |
| + |
| mDialog.show(); |
| + mPagerView.setVisibility(View.INVISIBLE); |
|
Theresa
2017/05/19 17:19:30
nit: I would move this visibility change and the l
Daniel Park
2017/05/22 18:12:55
Done.
|
| + mPagerView.addOnLayoutChangeListener(new OnLayoutChangeListener() { |
| + |
| + @Override |
| + public void onLayoutChange(View v, int left, int top, int right, int bottom, |
| + int oldLeft, int oldTop, int oldRight, int oldBottom) { |
| + if (mContextMenuHeight == -1) { |
|
Theresa
2017/05/19 17:19:30
Rather than relying on mContextMenuHeight == -1, l
Daniel Park
2017/05/22 18:12:55
Done.
|
| + mContextMenuHeight = v.getHeight(); |
| + initializeAnimationAndRevealView(touchPointX, touchPointY); |
| + } |
| + } |
| + }); |
| } |
| /** |
| @@ -84,10 +123,54 @@ public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl |
| * @return Returns a final dialog that does not have a background can be displayed using |
| * {@link AlertDialog#show()}. |
| */ |
| + @SuppressWarnings("deprecation") |
|
Theresa
2017/05/19 17:19:30
What method is deprecated?
Daniel Park
2017/05/22 18:12:55
Done.
|
| private Dialog createDialog(Activity activity, ContextMenuParams params, |
| List<Pair<Integer, List<ContextMenuItem>>> itemGroups) { |
| - Dialog dialog = new Dialog(activity); |
| - dialog.setContentView(createPagerView(activity, params, itemGroups)); |
| + final Dialog dialog = new AlwaysDismissedDialog(activity, R.style.DialogWhenLarge); |
| + |
| + dialog.findViewById(android.R.id.content).setOnClickListener(new OnClickListener() { |
| + @Override |
| + public void onClick(View v) { |
| + int[] outLocation = new int[2]; |
| + mPagerView.getLocationOnScreen(outLocation); |
| + mContextMenuSourceY = |
| + mContextMenuSourceY + (mContextMenuLocationOnScreen - outLocation[1]); |
| + Animation exitAnimation = getScaleAnimation(false); |
| + exitAnimation.setAnimationListener(new AnimationListener() { |
| + |
| + @Override |
| + public void onAnimationStart(Animation animation) {} |
| + |
| + @Override |
| + public void onAnimationRepeat(Animation animation) {} |
| + |
| + @Override |
| + public void onAnimationEnd(Animation animation) { |
| + dialog.dismiss(); |
| + } |
| + }); |
| + mPagerView.startAnimation(exitAnimation); |
| + mContextMenuHeight = -1; |
|
Theresa
2017/05/19 17:19:30
Each time the context menu is displayed, a new Dia
Daniel Park
2017/05/22 18:12:55
Done.
|
| + } |
| + }); |
| + |
| + FrameLayout mFullContainer = new FrameLayout(activity); |
| + mFullContainer.setBackgroundColor(ApiCompatibilityUtils.getColor( |
| + activity.getResources(), R.color.modal_dialog_scrim_color)); |
| + |
| + mContextMenuWidth = |
| + (int) Math.min(Resources.getSystem().getDisplayMetrics().widthPixels * 0.75, 1000); |
|
Theresa
2017/05/19 17:19:30
0.75 should be defined as private static final MAX
Daniel Park
2017/05/22 18:12:55
Done.
|
| + |
| + FrameLayout.LayoutParams layoutParams = |
| + new FrameLayout.LayoutParams(mContextMenuWidth, LayoutParams.MATCH_PARENT); |
| + layoutParams.gravity = Gravity.CENTER; |
| + |
| + mPagerView = createPagerView(activity, params, itemGroups); |
| + |
| + mFullContainer.addView(mPagerView, layoutParams); |
| + dialog.addContentView(mFullContainer, |
| + new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); |
| + |
| return dialog; |
| } |
| @@ -103,6 +186,8 @@ public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl |
| View createPagerView(Activity activity, ContextMenuParams params, |
| List<Pair<Integer, List<ContextMenuItem>>> itemGroups) { |
| View view = LayoutInflater.from(activity).inflate(R.layout.tabular_context_menu, null); |
| + view.findViewById(R.id.custom_pager) |
| + .setBackgroundResource(R.drawable.white_with_rounded_corners); |
|
Theresa
2017/05/19 17:19:30
Let's set the background in tabular_context_menu.x
Daniel Park
2017/05/22 18:12:55
Done.
|
| List<Pair<String, ViewGroup>> viewGroups = new ArrayList<>(); |
| int maxCount = 0; |
| @@ -118,21 +203,15 @@ public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl |
| createContextMenuPageUi( |
| activity, params, itemGroup.second, isImageTab, maxCount))); |
| } |
| - if (itemGroups.size() == 1) { |
| - viewGroups.get(0) |
| - .second.getChildAt(0) |
| - .findViewById(R.id.context_header_layout) |
| - .setBackgroundResource(R.color.google_grey_100); |
| - } |
| TabularContextMenuViewPager pager = |
| (TabularContextMenuViewPager) view.findViewById(R.id.custom_pager); |
| pager.setAdapter(new TabularContextMenuPagerAdapter(viewGroups)); |
| - |
| TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout); |
| if (itemGroups.size() <= 1) { |
| tabLayout.setVisibility(View.GONE); |
| } else { |
| + tabLayout.setBackgroundResource(R.drawable.grey_with_top_rounded_corners); |
| tabLayout.setupWithViewPager((ViewPager) view.findViewById(R.id.custom_pager)); |
| } |
| @@ -263,6 +342,41 @@ public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl |
| } |
| /** |
| + * @param touchPointX The x-coordinate of the pixel where the touch was registered |
| + * @param touchPointY The y-coordinate of the pixel where the touch was registered |
| + */ |
| + private void initializeAnimationAndRevealView( |
| + final float touchPointX, final float touchPointY) { |
| + mPagerView.setVisibility(View.VISIBLE); |
| + |
| + int[] locationOnScreen = new int[2]; |
| + mPagerView.getLocationOnScreen(locationOnScreen); |
| + |
| + mContextMenuLocationOnScreen = locationOnScreen[1]; |
| + mPagerView.startAnimation( |
| + initAnimations(touchPointX, touchPointY, locationOnScreen[0], locationOnScreen[1])); |
| + } |
| + |
| + /** |
| + * @param startX The starting x-coordinate of the translation animation |
|
Theresa
2017/05/19 17:19:30
nit: add a period to the end of all param descript
Daniel Park
2017/05/22 18:12:55
Done.
|
| + * @param startY The starting y-coordinate of the translation animation |
| + * @param viewLocationX The x-coordinate of the top left corner of the view relative to the |
| + * device |
| + * @param viewLocationY The y-coordinate of the top left corner of the view relative to the |
| + * device |
| + * @return Returns the animation set containing the scale & translation animations with the |
| + * pivots set relative to the view because 0, 0 is relative to the view, not the device |
| + * window |
| + */ |
| + protected Animation initAnimations(final float touchPointX, final float touchPointY, |
| + int viewLocationX, int viewLocationY) { |
| + float offset = mContentViewCore.getRenderCoordinates().getContentOffsetYPix(); |
|
Theresa
2017/05/19 17:19:30
nit: Add a comment about why this is necessary.
I
Daniel Park
2017/05/22 18:12:55
Done.
|
| + mContextMenuSourceX = touchPointX - viewLocationX; |
| + mContextMenuSourceY = touchPointY - viewLocationY + offset; |
| + return getScaleAnimation(true); |
| + } |
| + |
| + /** |
| * When an thumbnail is retrieved for the header of an image, this will set the header to |
| * that particular bitmap. |
| */ |
| @@ -277,4 +391,23 @@ public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl |
| mDialog.dismiss(); |
| mCallback.onResult((int) id); |
| } |
| + |
| + public void setContentViewCore(ContentViewCore contentViewCore) { |
|
Theresa
2017/05/19 17:19:30
nit: JavaDoc for this public method
Daniel Park
2017/05/22 18:12:55
Done.
|
| + mContentViewCore = contentViewCore; |
| + } |
| + |
| + private Animation getScaleAnimation(boolean comingIn) { |
| + float fromX = comingIn ? 0f : 1f; |
| + float toX = comingIn ? 1f : 0f; |
| + float fromY = fromX; |
| + float toY = toX; |
| + |
| + ScaleAnimation scaleAnimation = new ScaleAnimation(fromX, toX, fromY, toY, |
| + Animation.ABSOLUTE, mContextMenuSourceX, Animation.ABSOLUTE, mContextMenuSourceY); |
|
Theresa
2017/05/19 17:19:30
On dismiss, is the context menu disappearing back
Daniel Park
2017/05/22 18:12:55
The updated design asks for it to go back to the t
|
| + |
| + long duration = (long) (comingIn ? 250 : (250 * 0.6)); |
|
Theresa
2017/05/19 17:19:30
These int's should be defined as "private static f
Daniel Park
2017/05/22 18:12:55
Done.
|
| + scaleAnimation.setDuration(duration); |
| + scaleAnimation.setInterpolator(new LinearOutSlowInInterpolator()); |
| + return scaleAnimation; |
| + } |
| } |