Loading core/java/android/widget/SearchView.java +151 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,10 @@ import android.util.TypedValue; import android.view.CollapsibleActionView; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.TouchDelegate; import android.view.View; import android.view.ViewConfiguration; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView.OnItemClickListener; Loading Loading @@ -111,6 +114,12 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { private final ImageView mVoiceButton; private final View mDropDownAnchor; private UpdatableTouchDelegate mTouchDelegate; private Rect mSearchSrcTextViewBounds = new Rect(); private Rect mSearchSrtTextViewBoundsExpanded = new Rect(); private int[] mTemp = new int[2]; private int[] mTemp2 = new int[2]; /** Icon optionally displayed when the SearchView is collapsed. */ private final ImageView mCollapsedIcon; Loading Loading @@ -801,7 +810,48 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { break; } widthMode = MeasureSpec.EXACTLY; super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); switch (heightMode) { case MeasureSpec.AT_MOST: case MeasureSpec.UNSPECIFIED: height = Math.min(getPreferredHeight(), height); break; } heightMode = MeasureSpec.EXACTLY; super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), MeasureSpec.makeMeasureSpec(height, heightMode)); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (changed) { // Expand mSearchSrcTextView touch target to be the height of the parent in order to // allow it to be up to 48dp. getChildBoundsWithinSearchView(mSearchSrcTextView, mSearchSrcTextViewBounds); mSearchSrtTextViewBoundsExpanded.set( mSearchSrcTextViewBounds.left, 0, mSearchSrcTextViewBounds.right, bottom - top); if (mTouchDelegate == null) { mTouchDelegate = new UpdatableTouchDelegate(mSearchSrtTextViewBoundsExpanded, mSearchSrcTextViewBounds, mSearchSrcTextView); setTouchDelegate(mTouchDelegate); } else { mTouchDelegate.setBounds(mSearchSrtTextViewBoundsExpanded, mSearchSrcTextViewBounds); } } } private void getChildBoundsWithinSearchView(View view, Rect rect) { view.getLocationInWindow(mTemp); getLocationInWindow(mTemp2); final int top = mTemp[1] - mTemp2[1]; final int left = mTemp[0] - mTemp2[0]; rect.set(left , top, left + view.getWidth(), top + view.getHeight()); } private int getPreferredWidth() { Loading @@ -809,6 +859,11 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { .getDimensionPixelSize(R.dimen.search_view_preferred_width); } private int getPreferredHeight() { return getContext().getResources() .getDimensionPixelSize(R.dimen.search_view_preferred_height); } private void updateViewsVisibility(final boolean collapsed) { mIconified = collapsed; // Visibility of views that are visible when collapsed Loading Loading @@ -1749,6 +1804,101 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { } }; private static class UpdatableTouchDelegate extends TouchDelegate { /** * View that should receive forwarded touch events */ private final View mDelegateView; /** * Bounds in local coordinates of the containing view that should be mapped to the delegate * view. This rect is used for initial hit testing. */ private final Rect mTargetBounds; /** * Bounds in local coordinates of the containing view that are actual bounds of the delegate * view. This rect is used for event coordinate mapping. */ private final Rect mActualBounds; /** * mTargetBounds inflated to include some slop. This rect is to track whether the motion events * should be considered to be be within the delegate view. */ private final Rect mSlopBounds; private final int mSlop; /** * True if the delegate had been targeted on a down event (intersected mTargetBounds). */ private boolean mDelegateTargeted; public UpdatableTouchDelegate(Rect targetBounds, Rect actualBounds, View delegateView) { super(targetBounds, delegateView); mSlop = ViewConfiguration.get(delegateView.getContext()).getScaledTouchSlop(); mTargetBounds = new Rect(); mSlopBounds = new Rect(); mActualBounds = new Rect(); setBounds(targetBounds, actualBounds); mDelegateView = delegateView; } public void setBounds(Rect desiredBounds, Rect actualBounds) { mTargetBounds.set(desiredBounds); mSlopBounds.set(desiredBounds); mSlopBounds.inset(-mSlop, -mSlop); mActualBounds.set(actualBounds); } @Override public boolean onTouchEvent(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); boolean sendToDelegate = false; boolean hit = true; boolean handled = false; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (mTargetBounds.contains(x, y)) { mDelegateTargeted = true; sendToDelegate = true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_MOVE: sendToDelegate = mDelegateTargeted; if (sendToDelegate) { if (!mSlopBounds.contains(x, y)) { hit = false; } } break; case MotionEvent.ACTION_CANCEL: sendToDelegate = mDelegateTargeted; mDelegateTargeted = false; break; } if (sendToDelegate) { if (hit && !mActualBounds.contains(x, y)) { // Offset event coordinates to be in the center of the target view since we // are within the targetBounds, but not inside the actual bounds of // mDelegateView event.setLocation(mDelegateView.getWidth() / 2, mDelegateView.getHeight() / 2); } else { // Offset event coordinates to the target view coordinates. event.setLocation(x - mActualBounds.left, y - mActualBounds.top); } handled = mDelegateView.dispatchTouchEvent(event); } return handled; } } /** * Local subclass for AutoCompleteTextView. * @hide Loading core/res/res/layout/search_view.xml +3 −6 Original line number Diff line number Diff line Loading @@ -48,11 +48,8 @@ <LinearLayout android:id="@+id/search_edit_frame" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:layout_gravity="center_vertical" android:layout_marginTop="4dip" android:layout_marginBottom="4dip" android:layout_marginStart="8dip" android:layout_marginEnd="8dip" android:orientation="horizontal" Loading @@ -71,7 +68,7 @@ <LinearLayout android:id="@+id/search_plate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:layout_gravity="center_vertical" android:orientation="horizontal"> Loading @@ -81,7 +78,7 @@ android:layout_height="36dip" android:layout_width="0dp" android:layout_weight="1" android:layout_gravity="bottom" android:layout_gravity="center_vertical" android:paddingStart="@dimen/dropdownitem_text_padding_left" android:paddingEnd="@dimen/dropdownitem_text_padding_right" android:singleLine="true" Loading core/res/res/values/dimens.xml +2 −1 Original line number Diff line number Diff line Loading @@ -184,8 +184,9 @@ <!-- The spacing between messages in Notification.MessagingStyle --> <dimen name="notification_messaging_spacing">6dp</dimen> <!-- Preferred width of the search view. --> <!-- Preferred width and height of the search view. --> <dimen name="search_view_preferred_width">320dip</dimen> <dimen name="search_view_preferred_height">48dip</dimen> <!-- Dialog padding for round display --> <dimen name="alert_dialog_round_padding">27dip</dimen> Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -423,6 +423,7 @@ <java-symbol type="dimen" name="dropdownitem_text_padding_left" /> <java-symbol type="dimen" name="password_keyboard_spacebar_vertical_correction" /> <java-symbol type="dimen" name="search_view_preferred_width" /> <java-symbol type="dimen" name="search_view_preferred_height" /> <java-symbol type="dimen" name="textview_error_popup_default_width" /> <java-symbol type="dimen" name="toast_y_offset" /> <java-symbol type="dimen" name="action_bar_stacked_max_height" /> Loading Loading
core/java/android/widget/SearchView.java +151 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,10 @@ import android.util.TypedValue; import android.view.CollapsibleActionView; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.TouchDelegate; import android.view.View; import android.view.ViewConfiguration; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView.OnItemClickListener; Loading Loading @@ -111,6 +114,12 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { private final ImageView mVoiceButton; private final View mDropDownAnchor; private UpdatableTouchDelegate mTouchDelegate; private Rect mSearchSrcTextViewBounds = new Rect(); private Rect mSearchSrtTextViewBoundsExpanded = new Rect(); private int[] mTemp = new int[2]; private int[] mTemp2 = new int[2]; /** Icon optionally displayed when the SearchView is collapsed. */ private final ImageView mCollapsedIcon; Loading Loading @@ -801,7 +810,48 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { break; } widthMode = MeasureSpec.EXACTLY; super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); switch (heightMode) { case MeasureSpec.AT_MOST: case MeasureSpec.UNSPECIFIED: height = Math.min(getPreferredHeight(), height); break; } heightMode = MeasureSpec.EXACTLY; super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), MeasureSpec.makeMeasureSpec(height, heightMode)); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (changed) { // Expand mSearchSrcTextView touch target to be the height of the parent in order to // allow it to be up to 48dp. getChildBoundsWithinSearchView(mSearchSrcTextView, mSearchSrcTextViewBounds); mSearchSrtTextViewBoundsExpanded.set( mSearchSrcTextViewBounds.left, 0, mSearchSrcTextViewBounds.right, bottom - top); if (mTouchDelegate == null) { mTouchDelegate = new UpdatableTouchDelegate(mSearchSrtTextViewBoundsExpanded, mSearchSrcTextViewBounds, mSearchSrcTextView); setTouchDelegate(mTouchDelegate); } else { mTouchDelegate.setBounds(mSearchSrtTextViewBoundsExpanded, mSearchSrcTextViewBounds); } } } private void getChildBoundsWithinSearchView(View view, Rect rect) { view.getLocationInWindow(mTemp); getLocationInWindow(mTemp2); final int top = mTemp[1] - mTemp2[1]; final int left = mTemp[0] - mTemp2[0]; rect.set(left , top, left + view.getWidth(), top + view.getHeight()); } private int getPreferredWidth() { Loading @@ -809,6 +859,11 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { .getDimensionPixelSize(R.dimen.search_view_preferred_width); } private int getPreferredHeight() { return getContext().getResources() .getDimensionPixelSize(R.dimen.search_view_preferred_height); } private void updateViewsVisibility(final boolean collapsed) { mIconified = collapsed; // Visibility of views that are visible when collapsed Loading Loading @@ -1749,6 +1804,101 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { } }; private static class UpdatableTouchDelegate extends TouchDelegate { /** * View that should receive forwarded touch events */ private final View mDelegateView; /** * Bounds in local coordinates of the containing view that should be mapped to the delegate * view. This rect is used for initial hit testing. */ private final Rect mTargetBounds; /** * Bounds in local coordinates of the containing view that are actual bounds of the delegate * view. This rect is used for event coordinate mapping. */ private final Rect mActualBounds; /** * mTargetBounds inflated to include some slop. This rect is to track whether the motion events * should be considered to be be within the delegate view. */ private final Rect mSlopBounds; private final int mSlop; /** * True if the delegate had been targeted on a down event (intersected mTargetBounds). */ private boolean mDelegateTargeted; public UpdatableTouchDelegate(Rect targetBounds, Rect actualBounds, View delegateView) { super(targetBounds, delegateView); mSlop = ViewConfiguration.get(delegateView.getContext()).getScaledTouchSlop(); mTargetBounds = new Rect(); mSlopBounds = new Rect(); mActualBounds = new Rect(); setBounds(targetBounds, actualBounds); mDelegateView = delegateView; } public void setBounds(Rect desiredBounds, Rect actualBounds) { mTargetBounds.set(desiredBounds); mSlopBounds.set(desiredBounds); mSlopBounds.inset(-mSlop, -mSlop); mActualBounds.set(actualBounds); } @Override public boolean onTouchEvent(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); boolean sendToDelegate = false; boolean hit = true; boolean handled = false; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (mTargetBounds.contains(x, y)) { mDelegateTargeted = true; sendToDelegate = true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_MOVE: sendToDelegate = mDelegateTargeted; if (sendToDelegate) { if (!mSlopBounds.contains(x, y)) { hit = false; } } break; case MotionEvent.ACTION_CANCEL: sendToDelegate = mDelegateTargeted; mDelegateTargeted = false; break; } if (sendToDelegate) { if (hit && !mActualBounds.contains(x, y)) { // Offset event coordinates to be in the center of the target view since we // are within the targetBounds, but not inside the actual bounds of // mDelegateView event.setLocation(mDelegateView.getWidth() / 2, mDelegateView.getHeight() / 2); } else { // Offset event coordinates to the target view coordinates. event.setLocation(x - mActualBounds.left, y - mActualBounds.top); } handled = mDelegateView.dispatchTouchEvent(event); } return handled; } } /** * Local subclass for AutoCompleteTextView. * @hide Loading
core/res/res/layout/search_view.xml +3 −6 Original line number Diff line number Diff line Loading @@ -48,11 +48,8 @@ <LinearLayout android:id="@+id/search_edit_frame" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:layout_gravity="center_vertical" android:layout_marginTop="4dip" android:layout_marginBottom="4dip" android:layout_marginStart="8dip" android:layout_marginEnd="8dip" android:orientation="horizontal" Loading @@ -71,7 +68,7 @@ <LinearLayout android:id="@+id/search_plate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:layout_gravity="center_vertical" android:orientation="horizontal"> Loading @@ -81,7 +78,7 @@ android:layout_height="36dip" android:layout_width="0dp" android:layout_weight="1" android:layout_gravity="bottom" android:layout_gravity="center_vertical" android:paddingStart="@dimen/dropdownitem_text_padding_left" android:paddingEnd="@dimen/dropdownitem_text_padding_right" android:singleLine="true" Loading
core/res/res/values/dimens.xml +2 −1 Original line number Diff line number Diff line Loading @@ -184,8 +184,9 @@ <!-- The spacing between messages in Notification.MessagingStyle --> <dimen name="notification_messaging_spacing">6dp</dimen> <!-- Preferred width of the search view. --> <!-- Preferred width and height of the search view. --> <dimen name="search_view_preferred_width">320dip</dimen> <dimen name="search_view_preferred_height">48dip</dimen> <!-- Dialog padding for round display --> <dimen name="alert_dialog_round_padding">27dip</dimen> Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -423,6 +423,7 @@ <java-symbol type="dimen" name="dropdownitem_text_padding_left" /> <java-symbol type="dimen" name="password_keyboard_spacebar_vertical_correction" /> <java-symbol type="dimen" name="search_view_preferred_width" /> <java-symbol type="dimen" name="search_view_preferred_height" /> <java-symbol type="dimen" name="textview_error_popup_default_width" /> <java-symbol type="dimen" name="toast_y_offset" /> <java-symbol type="dimen" name="action_bar_stacked_max_height" /> Loading