Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(553)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/contextmenu/CustomContextMenuDialog.java

Issue 2751333006: Create the base Custom Context Menu Dialog. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/contextmenu/CustomContextMenuDialog.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/CustomContextMenuDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/CustomContextMenuDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1be9fc8c85f26f5bfebcca62a8098ade7ad75b1
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/CustomContextMenuDialog.java
@@ -0,0 +1,162 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
Ted C 2017/03/21 16:29:39 2017
David Trainor- moved to gerrit 2017/03/21 16:30:02 2017
JJ 2017/03/22 23:35:32 Done.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.contextmenu;
+
+import android.app.Activity;
+import android.support.design.widget.TabLayout;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.AlertDialog;
+import android.util.Pair;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.Callback;
+import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A custom dialog that separates each group into separate tabs. It uses a dialog instead.
+ */
+public class CustomContextMenuDialog implements ContextMenuUi, AdapterView.OnItemClickListener {
Ted C 2017/03/21 16:29:39 If the other name is PlatformContextMenuUi, I thin
JJ 2017/03/22 23:35:32 I've noted this and will change it shortly. I have
+ private AlertDialog mDialog;
David Trainor- moved to gerrit 2017/03/21 16:30:02 final?
JJ 2017/03/22 23:35:32 Can't be done since we don't call this in the cons
David Trainor- moved to gerrit 2017/03/23 04:58:47 Makes sense I misread "displayMenu" for the constr
+ private Callback<Integer> mCallback;
David Trainor- moved to gerrit 2017/03/21 16:30:02 final?
JJ 2017/03/22 23:35:32 Can't be done since we don't call this in the cons
+
+ @Override
+ public void displayMenu(Activity activity, ContextMenuParams params,
+ List<Pair<Integer, List<ContextMenuItem>>> items, Callback<Integer> onItemClicked) {
+ mCallback = onItemClicked;
+ mDialog = createDialog(activity, params, items);
+ mDialog.getWindow().setBackgroundDrawable(ApiCompatibilityUtils.getDrawable(
+ activity.getResources(), R.drawable.context_menu_bg));
+ mDialog.show();
+ }
+
+ /**
+ * Returns the fully complete dialog based off the params and the itemGroups.
+ * @param activity Used to inflate the dialog.
+ * @param params Used to get the header title.
+ * @param itemGroups If there is more than one group it will create a pagged view.
+ * @return Returns a final dialog that does not have a background can be displayed using
+ * {@link AlertDialog#show()}.
+ */
+ private AlertDialog createDialog(Activity activity, ContextMenuParams params,
David Trainor- moved to gerrit 2017/03/21 16:30:02 Should we have both createDialog and createFinalVi
JJ 2017/03/22 23:35:32 Yeah the view is used mostly for tests (that aren'
David Trainor- moved to gerrit 2017/03/23 04:58:47 I guess meant should we just roll createDialog int
+ List<Pair<Integer, List<ContextMenuItem>>> itemGroups) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setView(createFinalView(activity, itemGroups, params));
+ return builder.create();
+ }
+
+ /**
+ * This creates the view hosted within the dialog. Mainly used for testing.
David Trainor- moved to gerrit 2017/03/21 16:30:02 Maybe use "//" or turn it into a more real javadoc
JJ 2017/03/22 23:35:32 Done.
+ */
+ @VisibleForTesting
+ View createFinalView(Activity activity, List<Pair<Integer, List<ContextMenuItem>>> itemGroups,
+ ContextMenuParams params) {
+ return (itemGroups.size() == 1)
+ ? createSingleContextView(activity, itemGroups.get(0).second, params)
+ : createPagerView(itemGroups, activity, params);
+ }
+
+ /**
+ * Creates the view of a context menu. Based off the Context Type, it'll adjust the list of
+ * items and display only the ones that'll be on that specific group.
+ * @param activity Used to get the resources of an item.
+ * @param items A set of Items to display in a context menu. Filtered based off the type.
+ * @param params used to create the header text.
+ * @return Returns a filled LinearLayout based off custom_context_menu.xml.
+ */
+ private ViewGroup createSingleContextView(
+ Activity activity, List<ContextMenuItem> items, ContextMenuParams params) {
+ ViewGroup baseLayout = (ViewGroup) LayoutInflater.from(activity).inflate(
+ R.layout.custom_context_menu, null);
+ ListView listView = (ListView) baseLayout.findViewById(R.id.selectable_items);
+ TextView headerText = (TextView) baseLayout.findViewById(R.id.context_header_text);
+ headerText.setVisibility(View.VISIBLE);
+ headerText.setText(ChromeContextMenuPopulator.createHeaderText(params));
+
+ // Set the list adapter and get the height to display it appropriately in a dialog.
+ List<ContextMenuItem> itemsType = new ArrayList<>(items);
+ CustomContextMenuListAdapter listAdapter =
+ new CustomContextMenuListAdapter(itemsType, activity);
+ ViewGroup.LayoutParams layoutParams = listView.getLayoutParams();
+ layoutParams.height = measureApproximateListViewHeight(listView, listAdapter);
+ listView.setLayoutParams(layoutParams);
+ listView.requestLayout();
Ted C 2017/03/21 16:29:40 setLayoutParams does a requestlayout for you
David Trainor- moved to gerrit 2017/03/21 16:30:02 I think setLayoutParams does this?
JJ 2017/03/22 23:35:32 Thanks!
+ listView.setAdapter(listAdapter);
+ listView.setOnItemClickListener(this);
+ baseLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
David Trainor- moved to gerrit 2017/03/21 16:30:02 Could you explain why we need to measure baseLayou
JJ 2017/03/22 23:35:32 Oh we don't. Sorry, old experimentation got the be
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
+
+ return baseLayout;
+ }
+
+ /**
+ * To save time measuring the height, this method gets the first item and multiplies it by
Ted C 2017/03/21 16:29:39 I wouldn't call out the first item in this comment
JJ 2017/03/22 23:35:32 Done.
+ * count. It is fine if the height too small as the ListView will scroll through the other
+ * values.
+ * @param listView The ListView to measure the surrounding padding.
+ * @param listAdapter The adapter which contains the items within the list.
+ * @return Returns the combined height of the padding of the ListView and the approximate height
+ * of the ListView based off the first item.
+ */
+ private int measureApproximateListViewHeight(ListView listView, BaseAdapter listAdapter) {
+ int height = 0;
+ int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
+ if (!listAdapter.isEmpty()) {
+ View view = listAdapter.getView(0, null, listView);
+ view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
Ted C 2017/03/21 16:29:39 I don't "think" this does what you expect. By spe
JJ 2017/03/22 23:35:32 bugh. Thank you. Measurements are still a little f
David Trainor- moved to gerrit 2017/03/23 04:58:47 Does this still need to change?
JJ 2017/03/23 18:57:46 aha! Sorry I thought I redid this edit before send
Ted C 2017/03/24 04:32:53 Sorry, but I don't understand this comment. You a
JJ 2017/03/25 01:40:25 I think I've repeated this in a few other lines bu
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
+ height = view.getMeasuredHeight();
Ted C 2017/03/21 16:29:40 I don't think you need a height variable. I think
JJ 2017/03/22 23:35:32 Done.
+ }
+ totalHeight += (height * listAdapter.getCount());
+ return totalHeight;
+ }
+
+ /**
+ * Creates a ViewPageAdapter based off the given list of views.
+ * @param itemGroups The list of views to put into the ViewPager. The string is the title of the
+ * tab
+ * @param activity Used to inflate the new ViewPager
+ * @param params Used to get the header text.
+ * @return Returns a complete context menu based of image_link_context_menu.xml
+ */
+ private View createPagerView(List<Pair<Integer, List<ContextMenuItem>>> itemGroups,
+ Activity activity, ContextMenuParams params) {
+ LayoutInflater inflater = LayoutInflater.from(activity);
+ View view = inflater.inflate(R.layout.multi_type_context_menu, null);
David Trainor- moved to gerrit 2017/03/21 16:30:02 LayoutInflater.from(activity).inflate(...) like wh
JJ 2017/03/22 23:35:32 Done.
+
+ List<Pair<String, ViewGroup>> viewGroups = new ArrayList<>();
+ for (Pair<Integer, List<ContextMenuItem>> itemGroup : itemGroups) {
JJ 2017/03/17 20:58:20 If you're wondering why we switch from an Integer
+ viewGroups.add(new Pair<>(activity.getString(itemGroup.first),
+ createSingleContextView(activity, itemGroup.second, params)));
+ }
+
+ CustomContextMenuViewPager pager =
+ (CustomContextMenuViewPager) view.findViewById(R.id.custom_pager);
+ pager.setAdapter(new CustomContextMenuPagerAdapter(viewGroups));
+
+ TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout);
Ted C 2017/03/21 16:29:39 what happens if you set the visibility of the tabl
JJ 2017/03/22 23:35:32 O: It does! Wow I can't believe I didn't try that.
+ tabLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
+ tabLayout.setupWithViewPager((ViewPager) view.findViewById(R.id.custom_pager));
+
+ return view;
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
+ mDialog.dismiss();
+ mCallback.onResult((int) id);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698