如何以编程方式从设计支持库访问位于 NavigationView header 内的微调器?

How do I programatically access a spinner located inside the header of the NavigationView from the design support library?

我正在使用新的设计支持库。对于导航视图,您可以指定 header。我想要做的是 以编程方式访问微调器 ,它位于 nav_header xml.

Spinner spinner = (Spinner) findViewById(R.id.spinner); // Normal initialization of a spinner

位于activity_main.xml

<android.support.design.widget.NavigationView
        android:id="@+id/navigation_left"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header" <-- declaring nav_header as header layout
        app:itemIconTint="@color/primary_text"
        app:itemTextColor="@color/primary_text"
        app:menu="@menu/nav_draw_items" />

nav_header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/filter_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/actionBarSize"
        android:background="#2364AA"
        android:elevation="4dp"
        android:minHeight="?attr/actionBarSize"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:navigationContentDescription="@string/abc_action_bar_up_description"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        <LinearLayout
            android:id="@+id/spinner_ll"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/spinner_front"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="8dp"
                android:layout_gravity="center_vertical"
                android:text="Sort By: "
                android:textColor="@android:color/white"
                android:textSize="16sp"/>

            <Spinner
                android:id="@+id/spinner"           <-- what I'm trying to access
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawSelectorOnTop="true"
                android:spinnerMode="dropdown" />

        </LinearLayout>

    </android.support.v7.widget.Toolbar>

</LinearLayout>

做这样的事情:-

//Your navigation view
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_left);

//Now get the Spinner from the navigationView
Spinner spinner = (Spinner) navigationView.findViewById(R.id.spinner);

我不知道它是否对您有帮助,但我从 Header 的导航视图中获取所有视图的解决方案是基于 Google 的导航创建自定义视图拦截设置 header 视图的方法并根据其视图绑定数据绑定的视图,因此自定义 class 类似于:

/**
 * Created by pokawa on 25/10/15.
 */
public class CustomNavigationView extends NavigationView {
    private static final String EXCEPTION_TAG_NULL_HEADER = "CustomNavigationView";
    private static final String EXCEPTION_MESSAGE_NULL_HEADER = "You have to set a header first";

    private View header;

    public CustomNavigationView(Context context) {
        super(context);
    }

    public CustomNavigationView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * Overridden to store the header's view
     *
     * @param res header view id
     * @return header's view
     */
    @Override
    public View inflateHeaderView(int res) {
        header = super.inflateHeaderView(res);
        return header;
    }

    /**
     * Overridden to store the header's view
     *
     * @param view header
     */
    @Override
    public void addHeaderView(View view) {
        this.header = view;
        super.addHeaderView(view);
    }

    /**
     * Method used to retrieve header's data binding
     *
     * @return Header's view binding
     */
    public ViewDataBinding getHeaderDataBinding() {
        try{
            return DataBindingUtil.bind(header);
        } catch (NullPointerException exception) {
            Log.i(EXCEPTION_TAG_NULL_HEADER, EXCEPTION_MESSAGE_NULL_HEADER);
            throw exception;
        }
    }
}

而 XML 将是这样的:

<your.package.path.CustomNavigationView
        android:id="@+id/navigation_left"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header" <-- declaring nav_header as header layout
        app:itemIconTint="@color/primary_text"
        app:itemTextColor="@color/primary_text"
        app:menu="@menu/nav_draw_items" />

最后,一个如何检索数据绑定的示例:

    public class MainActivity extends BaseActivity {

        (...)
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            (...)
            YourLayoutBinding binding = DataBindingUtil.setContentView(this, R.layout.your_layout);
            NavHeaderBinding headerBinding = ((NavHeaderBinding) binding.navigationLeft.getHeaderDataBinding());
            Spinner spinner = headerBinding.spinnerLl;
            (...)
        }

        (...)
    }

PS:当然,我假设您正在使用 Google 的新功能(DataBinding),如果您正在使用另一种方法来注入视图(例如ButterKnife),我可以帮你解决这个问题。

再见。

在当前版本的设计支持库中,您可以简单地使用 getHeaderView 方法,例如

View header = navigationView.getHeaderView(0);
TextView loginName = (TextView) header.findViewById(R.id.loginName);
loginName.setText(mApiHelper.getName());