如何在点击并使用全宽时让Spinner项目显示在自身下方,就像在G + app上一样

and*_*per 7 android android-spinner material-design

背景

Google plus有一个类似微调的视图,可以显示很多项目,但所有项目都显示在自身下方:

在此输入图像描述

我需要在我自己的微调器中模仿这个(这就是我所说的),但是最近,Material-Design指南说(这里)Spinner应该把它的项放在自己的顶部,这就是支持库为它做的事情.

问题

我找不到恢复此行为的方法.我试过改变Spinner的风格,并在互联网上搜索了这个(这里).

问题

  1. 如何让旋转器在下面(或者更高,如果需要的话)使用它的项目,就像在Material Design之前一样,但是在G +上,以便它们占据全宽?

  2. G + Spinner是一种特殊的吗?它有名字吗?是否在指南的任何地方提到过?也许我可以使用的东西而不是普通的微调器?

and*_*per 21

好吧,Spinner如何将项目放在自身下方的解决方案就是添加:

<Spinner
...
android:overlapAnchor="false" />
Run Code Online (Sandbox Code Playgroud)

似乎甚至在Kitkat上工作,而不仅仅是在Lollipop上工作,所以我的猜测是它也应该适用于以前的版本.

但是,我仍然想知道它是如何在G +上工作的,如果有教程/样本,那就是我在那里看到的.

我不知道,例如,如何使窗口看起来不像窗口.

我试过这个:

android:dropDownWidth="match_parent"
android:popupBackground="#FFffffff" 
android:popupElevation="0px"
Run Code Online (Sandbox Code Playgroud)

但它没有帮助,因为正确的区域没有被旋转器物品覆盖.

我也尝试使用看起来像微调器的TextView,并为它创建一个PopupMenu,但我仍然遇到同样的问题:

PopupMenu popupMenu = new PopupMenu(getActivity(), v, Gravity.NO_GRAVITY, R.attr.popupMenuStyle, R.style.PopupMenuFullWidthStyle);

<style name="PopupMenuFullWidthStyle" parent="@style/Widget.AppCompat.PopupMenu">
    <!--<item name="android:dropDownWidth">match_parent</item>-->
    <item name="android:popupBackground">#FFFFFFFF</item>
</style>
Run Code Online (Sandbox Code Playgroud)

它没有使用样式做任何事情.


完整解决方案

由于按照我的指示自定义PopupMenu非常困难,我已经为它做了一个完整的解决方案.以下是相关部分:

这将触发显示微调器的弹出窗口(实际上充当微调器):

<com.example.user.myapplication.FullSizeFakeSpinner
    android:id="@+id/spinner"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/spinner_selector"
    android:gravity="start|center_vertical"
    android:minHeight="44dp"
    android:paddingLeft="8dp"
    android:paddingRight="8dp"
    android:text="Fake Spinner"
    tools:ignore="UnusedAttribute"/>
Run Code Online (Sandbox Code Playgroud)

MainActivity.java     private static final String [] ITEMS = {"Item 0","Item 1"};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    FullSizeFakeSpinner spinner = (FullSizeFakeSpinner) findViewById(R.id.spinner);
    spinner.setItems(ITEMS);
    }
Run Code Online (Sandbox Code Playgroud)

FullSizeFakeSpinner

public class FullSizeFakeSpinner extends TextView {
    private String[] mItems;
    private int mSelectedItemPosition = -1;
    private PopupWindow mPopupWindow;
    private boolean mInitialized = false;
    private OnItemClickListener mOnItemSelectedListener;

    public interface OnItemClickListener {
        void onItemClick(FullSizeFakeSpinner parent, View clickedView, int position, String item);

        void onNothingSelected(FullSizeFakeSpinner parent);
    }

    public FullSizeFakeSpinner(final Context context) {
        super(context);
        init(context);
    }

    public FullSizeFakeSpinner(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public FullSizeFakeSpinner(final Context context, final AttributeSet attrs, final int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @Override
    public Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);
        ss.mSelectedItemPosition = this.mSelectedItemPosition;
        ss.mItems = mItems;
        return ss;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        if (!(state instanceof SavedState)) {
            super.onRestoreInstanceState(state);
            return;
        }
        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());
        setItems(ss.mItems);
        setSelectedItemPosition(ss.mSelectedItemPosition);
    }

    public String[] getItems() {
        return mItems;
    }

    public void setItems(final String[] items) {
        mItems = items;
        if (mItems != null && mSelectedItemPosition >= 0 && mSelectedItemPosition < mItems.length)
            setText(mItems[mSelectedItemPosition]);
    }

    public int getSelectedItemPosition() {
        return mSelectedItemPosition;
    }

    public void setSelectedItemPosition(final int selectedItemPosition) {
        mSelectedItemPosition = selectedItemPosition;
        if (mItems != null && mSelectedItemPosition >= 0 && mSelectedItemPosition < mItems.length)
            setText(mItems[mSelectedItemPosition]);
    }

    public void setOnItemSelectedListener(OnItemClickListener onItemSelectedListener) {
        mOnItemSelectedListener = onItemSelectedListener;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mPopupWindow != null)
            mPopupWindow.dismiss();
    }


    protected void init(final Context context) {
        if (mInitialized)
            return;
        mInitialized = true;
        setSaveEnabled(true);
        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                if (mItems == null)
                    return;
                LayoutInflater layoutInflater = LayoutInflater.from(context);
                final View popupView = layoutInflater.inflate(R.layout.spinner_drop_down_popup, null, false);
                final LinearLayout linearLayout = (LinearLayout) popupView.findViewById(android.R.id.list);
                linearLayout.setOrientation(LinearLayout.VERTICAL);
                mPopupWindow = new PopupWindow(popupView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
                mPopupWindow.setOutsideTouchable(true);
                mPopupWindow.setTouchable(true);
                mPopupWindow.setBackgroundDrawable(new ColorDrawable(0));
                mPopupWindow.setFocusable(true);
                final AtomicBoolean isItemSelected = new AtomicBoolean(false);
                for (int i = 0; i < mItems.length; ++i) {
                    final String item = mItems[i];
                    final int position = i;
                    View itemView = layoutInflater.inflate(android.R.layout.simple_list_item_1, linearLayout, false);
                    itemView.setBackgroundResource(R.drawable.listview_white_selector);
                    itemView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
                    ((TextView) itemView.findViewById(android.R.id.text1)).setText(item);
                    linearLayout.addView(itemView, linearLayout.getChildCount() - 1);
                    itemView.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(final View v) {
                            isItemSelected.set(true);
                            mPopupWindow.dismiss();
                            mSelectedItemPosition = position;
                            setText(item);
                            if (mOnItemSelectedListener != null)
                                mOnItemSelectedListener.onItemClick(FullSizeFakeSpinner.this, v, position, item);
                        }
                    });
                }
                popupView.findViewById(android.R.id.empty).setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(final View v) {
                        mPopupWindow.dismiss();
                    }
                });
                mPopupWindow.setOnDismissListener(new OnDismissListener() {
                    @Override
                    public void onDismiss() {
                        setViewBackgroundWithoutResettingPadding(FullSizeFakeSpinner.this, R.drawable.spinner_selector);
                        if (!isItemSelected.get() && mOnItemSelectedListener != null)
                            mOnItemSelectedListener.onNothingSelected(FullSizeFakeSpinner.this);
                    }
                });
                // optional: set animation style. look here for more info: http://stackoverflow.com/q/9648797/878126
                mPopupWindow.showAsDropDown(v, 0, 0);
                setViewBackgroundWithoutResettingPadding(FullSizeFakeSpinner.this, R.drawable.spinner_opened_selector);
            }
        });

    }

    public static void setViewBackgroundWithoutResettingPadding(final View v, final int backgroundResId) {
        final int paddingBottom = v.getPaddingBottom(), paddingLeft = v.getPaddingLeft();
        final int paddingRight = v.getPaddingRight(), paddingTop = v.getPaddingTop();
        v.setBackgroundResource(backgroundResId);
        v.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
    }

    //////////////////////////////////////
    //SavedState//
    //////////////
    static class SavedState extends BaseSavedState {
        private String[] mItems;
        private int mSelectedItemPosition = -1;

        SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel in) {
            super(in);
            this.mItems = in.createStringArray();
            mSelectedItemPosition = in.readInt();
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeStringArray(mItems);
            out.writeInt(mSelectedItemPosition);
        }

        //required field that makes Parcelables from a Parcel
        public static final Parcelable.Creator<SavedState> CREATOR =
                new Parcelable.Creator<SavedState>() {
                    public SavedState createFromParcel(Parcel in) {
                        return new SavedState(in);
                    }

                    public SavedState[] newArray(int size) {
                        return new SavedState[size];
                    }
                };
    }

}
Run Code Online (Sandbox Code Playgroud)

这就是代码,但也有一些可绘制的资源:

应该有一个"spinner"图像文件,类似于支持库的"abc_spinner_mtrl_am_alpha",并且具有您希望使用的颜色.不知道如何在前Lollipop上使用色调,所以最好只使用您使用的颜色创建文件.

颜色:

<color name="listview_pressed">#FFE2E2E2</color>
<color name="listview_focused">#FF7dbcd3</color>
<color name="listview_checked">#FFededed</color>
Run Code Online (Sandbox Code Playgroud)

listview_white_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true"><shape>
        <solid android:color="@color/listview_pressed" />
    </shape></item>
    <item android:state_focused="true"><shape>
        <solid android:color="@color/listview_focused" />
    </shape></item>
    <item android:state_checked="true"><shape>
        <solid android:color="@color/listview_checked" />
    </shape></item>
    <item android:state_selected="true"><shape>
        <solid android:color="@color/listview_checked" />
    </shape></item>
    <item android:drawable="@android:color/white"/>

</selector>
Run Code Online (Sandbox Code Playgroud)

listview_white_selector.xml v21:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/listview_pressed">

    <item android:id="@android:id/mask">
        <color
            android:id="@android:id/mask"
            android:color="@color/listview_pressed"/>
    </item>
    <item android:drawable="@drawable/listview_ripple_white_background_selector"/>
</ripple>
Run Code Online (Sandbox Code Playgroud)

spinner_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <selector xmlns:android="http://schemas.android.com/apk/res/android">
            <item android:state_pressed="true">
                <shape>
                    <solid android:color="@color/listview_pressed"/>
                </shape>
            </item>
            <item android:state_focused="true">
                <shape>
                    <solid android:color="@color/listview_focused"/>
                </shape>
            </item>
            <item android:state_checked="true">
                <shape>
                    <solid android:color="@color/listview_checked"/>
                </shape>
            </item>
            <item android:state_selected="true">
                <shape>
                    <solid android:color="@color/listview_checked"/>
                </shape>
            </item>
            <item android:drawable="@android:color/transparent"/>
        </selector>
    </item>

    <item android:drawable="@drawable/spinner"/>

</layer-list>
Run Code Online (Sandbox Code Playgroud)

spinner_selector.xml(v21)

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/listview_pressed">
    <item android:drawable="@drawable/spinner"/>
    <item android:id="@android:id/mask">
        <color
            android:id="@android:id/mask"
            android:color="@color/listview_pressed"/>
    </item>
    <item android:drawable="@drawable/listview_ripple_background_selector"/>
</ripple>
Run Code Online (Sandbox Code Playgroud)

listview_ripple_white_background_selector:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true"><shape>
        <solid android:color="@color/listview_checked" />
    </shape></item>
    <item android:state_selected="true"><shape>
        <solid android:color="@color/listview_checked" />
    </shape></item>
    <item android:drawable="@android:color/white"/>

</selector>
Run Code Online (Sandbox Code Playgroud)

listview_ripple_background_selector:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true"><shape>
            <solid android:color="@color/listview_checked" />
        </shape></item>
    <item android:state_selected="true"><shape>
            <solid android:color="@color/listview_checked" />
        </shape></item>
    <item android:drawable="@android:color/transparent"/>

</selector>
Run Code Online (Sandbox Code Playgroud)

spinner_drop_down_popup

<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <LinearLayout
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical">

        <View
            android:id="@android:id/empty"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#33000000"/>
    </LinearLayout>
</ScrollView>
Run Code Online (Sandbox Code Playgroud)