1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.ui;
7 import android.content.Context;
8 import android.view.View;
9 import android.view.View.MeasureSpec;
10 import android.view.View.OnLayoutChangeListener;
11 import android.view.ViewGroup;
12 import android.widget.LinearLayout;
13 import android.widget.ListAdapter;
14 import android.widget.ListPopupWindow;
16 import org.chromium.ui.base.ViewAndroidDelegate;
19 * The dropdown list popup window.
21 public class DropdownPopupWindow extends ListPopupWindow {
23 private final Context mContext;
24 private final ViewAndroidDelegate mViewAndroidDelegate;
25 private final View mAnchorView;
26 private float mAnchorWidth;
27 private float mAnchorHeight;
28 private float mAnchorX;
29 private float mAnchorY;
30 private OnLayoutChangeListener mLayoutChangeListener;
33 * Creates an DropdownPopupWindow with specified parameters.
34 * @param context Application context.
35 * @param viewAndroidDelegate View delegate used to add and remove views.
37 public DropdownPopupWindow(Context context, ViewAndroidDelegate viewAndroidDelegate) {
38 super(context, null, 0, R.style.DropdownPopupWindow);
40 mViewAndroidDelegate = viewAndroidDelegate;
42 mAnchorView = mViewAndroidDelegate.acquireAnchorView();
43 mAnchorView.setId(R.id.dropdown_popup_window);
44 mAnchorView.setTag(this);
46 mLayoutChangeListener = new OnLayoutChangeListener() {
48 public void onLayoutChange(View v, int left, int top, int right, int bottom,
49 int oldLeft, int oldTop, int oldRight, int oldBottom) {
50 if (v == mAnchorView) DropdownPopupWindow.this.show();
54 mAnchorView.addOnLayoutChangeListener(mLayoutChangeListener);
55 setAnchorView(mAnchorView);
59 * Sets the location and the size of the anchor view that the DropdownPopupWindow will use to
61 * @param x X coordinate of the top left corner of the anchor view.
62 * @param y Y coordinate of the top left corner of the anchor view.
63 * @param width The width of the anchor view.
64 * @param height The height of the anchor view.
66 public void setAnchorRect(float x, float y, float width, float height) {
68 mAnchorHeight = height;
71 if (mAnchorView != null) {
72 mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY,
73 mAnchorWidth, mAnchorHeight);
79 // An ugly hack to keep the popup from expanding on top of the keyboard.
80 setInputMethodMode(INPUT_METHOD_NEEDED);
82 getListView().setDividerHeight(0);
83 int contentWidth = measureContentWidth();
84 float contentWidthInDip = contentWidth /
85 mContext.getResources().getDisplayMetrics().density;
86 if (contentWidthInDip > mAnchorWidth) {
87 setContentWidth(contentWidth);
89 setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
91 mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, mAnchorWidth,
96 public void dismiss() {
98 mAnchorView.removeOnLayoutChangeListener(mLayoutChangeListener);
99 mAnchorView.setTag(null);
100 mViewAndroidDelegate.releaseAnchorView(mAnchorView);
104 * Measures the width of the list content.
105 * @return The popup window width in pixels.
107 private int measureContentWidth() {
109 View itemView = null;
110 final ListAdapter adapter = getListView().getAdapter();
113 final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
114 final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
115 for (int i = 0; i < adapter.getCount(); i++) {
116 itemView = adapter.getView(i, itemView, null);
117 LinearLayout.LayoutParams params =
118 new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
119 LinearLayout.LayoutParams.WRAP_CONTENT);
120 itemView.setLayoutParams(params);
121 itemView.measure(widthMeasureSpec, heightMeasureSpec);
122 maxWidth = Math.max(maxWidth, itemView.getMeasuredWidth());