2015-08-27 6 views
20

Das ist also mein activity_main.xml:Wie bekomme ich die Ansicht vom Schubladen-Header-Layout mit der Bindung in Aktivität?

<?xml version="1.0" encoding="utf-8"?> 
<layout 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" 
     tools:context="MainActivity" 
    > 
    <!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. --> 
    <android.support.v4.widget.DrawerLayout 
     android:id="@+id/drawer_layout" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     > 

     <!-- As the main content view, the view below consumes the entire 
      space available using match_parent in both dimensions. --> 

     <RelativeLayout 
      android:layout_width="match_parent" 
      android:layout_height="match_parent"> 

      <LinearLayout 
       android:id="@+id/ll_container" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:orientation="vertical"> 

       <android.support.v7.widget.Toolbar 
        android:id="@+id/my_awesome_toolbar" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:background="@android:color/black" 
        android:fitsSystemWindows="true" 
        > 

        <TextView 
         android:id="@+id/toolbar_title" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" 
         android:layout_marginLeft="10dp" 
         android:layout_marginStart="10dp" 
         android:textColor="@android:color/white" 
         android:textSize="@dimen/abc_text_size_title_material_toolbar" 
         tools:text="@string/default_toolbar_title"/> 

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


       <FrameLayout 
        android:id="@+id/container" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent"> 

       </FrameLayout> 
      </LinearLayout> 

      <android.support.design.widget.FloatingActionButton 
       android:id="@+id/fab_fuf" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_alignParentBottom="true" 
       android:layout_alignParentEnd="true" 
       android:layout_alignParentRight="true" 
       android:layout_marginBottom="20dp" 
       android:layout_marginEnd="20dp" 
       android:layout_marginRight="20dp" 
       android:src="@drawable/flamme" 
       app:fabSize="normal" 
       /> 
     </RelativeLayout> 

     <android.support.design.widget.NavigationView 
      android:id="@+id/navigation_view" 
      android:layout_width="wrap_content" 
      android:layout_height="match_parent" 
      android:layout_gravity="start" 
      android:background="@android:color/black" 
      **app:headerLayout="@layout/drawer_header"** 
      app:itemTextColor="@color/drawer_item_color_selector" 
      app:menu="@menu/menu_drawer"/> 

    </android.support.v4.widget.DrawerLayout> 
</layout> 

und ich bin mit der Bindungsaktivität, so habe ich nicht die findViewById zu bedienen und es etc .. werfen wie folgt aus:

ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); 

     Toolbar toolbar = binding.myAwesomeToolbar; 
     toolbarTitle = binding.toolbarTitle; 
     BalrogFontsHelper.SetKhandBoldToView(toolbarTitle); 
     setSupportActionBar(toolbar); 
     final ActionBar actionBar = getSupportActionBar(); 
     if (actionBar != null) { 
      actionBar.setHomeAsUpIndicator(R.drawable.ic_dehaze_white_24); 
      actionBar.setDisplayHomeAsUpEnabled(true); 
      actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 
      actionBar.setDisplayShowTitleEnabled(false); 
     } 


     drawerLayout = binding.drawerLayout; 
     **tvLoggedUserEmail = (TextView) findViewById(R.id.tv_logged_user_email);** 
     BalrogFontsHelper.SetKhandBoldToView(tvLoggedUserEmail); 

Wie Sie sehen können, kann ich die Ansichten, die direkt im Layout activity_main.xml sind, durch Bindung abrufen, aber wenn die Ansicht, die ich versuche, nicht da ist, kann ich die Variable im Bindungsobjekt nicht sehen.

drawer_header.xml:

<?xml version="1.0" encoding="utf-8"?> 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:layout_width="match_parent" 
       android:layout_height="96dp" 
       xmlns:tools="http://schemas.android.com/tools" 
       android:background="@android:color/black" 
       android:theme="@style/ThemeOverlay.AppCompat.Dark"> 


    <TextView 
     android:id="@+id/tv_logged_user_email" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerVertical="true" 
     android:layout_marginLeft="16dp" 
     tools:text="@string/login_placeholder_email" 
     android:textAllCaps="true" 
     android:textAppearance="@style/TextAppearance.AppCompat.Body2" 
     android:textSize="20sp"/> 


</RelativeLayout> 

Wie kann ich diesen tv_logged_user_email Textview in einer verbindlichen Art und Weise erhalten, also ich habe:

**tvLoggedUserEmail = binding.tvLoggedUserEmail;** 

Antwort

31

13/11/2015

http://developer.android.com/tools/support-library/index.html

Update Design Support-Bibliothek 23.1.0 bis 23.1.1

Changes for Design Support library: Added the getHeaderView method to the NavigationView class. Fixed a transparent background issue for a FloatingActionButton object on devices running Android 4.0 (API level 15) and lower. (Issue 183315)

==== ==============

Ich weiß nicht, warum kein Verfahren gibt, das durch programmatisch angebracht Kopfansicht Bereitstellung

1.solution

NavigationView navigationView = (NavigationView) findViewById(R.id.navigation); 
View headerView = navigationView.inflateHeaderView(R.layout.header_layout) 
ImageView iv = (ImageView)headerview.findViewById(...) 

2.solution

NavigationView navigationView = (NavigationView) findViewById(R.id.navigation); 
View headerView = LayoutInflater.from(this).inflate(R.layout.header_layout, navigationView, false); 
navigationView.addHeaderView(view); 

ImageView iv = (ImageView) headerView.findViewById(...) 
+5

Aktualisieren Sie einfach Ihre Gradle-Datei, um 23.1.1 zu erhalten, und die Methode getHeaderView (int index) ist da. – Renascienza

+4

Lebensretter !! +1 .. Aber Sie müssen app entfernen: headerLayout = "@ Layout/header_left" von XML andernfalls wird es zwei Header aufblasen ... –

+4

Diese Lösung verwendet keine Datenbindung ... – Mussa

10

Ich habe/hatte das gleiche Problem.

Eine Problemumgehung besteht darin, die Header-Ansicht aufzublähen und sie programmatisch hinzuzufügen.

So:

DrawerHeaderBinding drawerHeaderBinding = DrawerHeaderBinding.inflate(LayoutInflater.from(navigationView.getContext())); 
navigationView.addHeaderView(drawerHeaderBinding.getRoot()); 
drawerHeaderBinding.tvLoggedUserEmail = "email"; 
drawerHeaderBinding.executePendingBindings(); 

entfernen So die App: headerLayout und es programmatisch tun. Ich denke, Google sollte das Kernproblem hier beheben, entweder in der Design-Bibliothek oder in der Datenbindungsbibliothek.

+0

Höhe zu halten von RelativeLayout in layout_height angegeben, setzen RelativeLayout in Frame-Layout: ' ' – geekyvad

+1

Haben Sie Änderungen in design-23.1.0 bemerkt? Mein Code würde jetzt nicht funktionieren. – RogerParis

-2

Sie können dies tun. Initialisieren Sie zuerst die Navigationsansicht.

NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view); 

und initialisieren Sie dann alle Ansichten innerhalb von navigationView.

CircleImageView circleView = (CircleImageView) navigationView.findViewById(R.id.circleView); 
    TextView name = (TextView) navigationView.findViewById(R.id.name); 
    TextView email = (TextView) navigationView.findViewById(R.id.email); 
    LinearLayout header = (LinearLayout) navigationView.findViewById(R.id.header); 

und dann können Sie diese Ansichten verwenden, wie Sie möchten. zB:

 name.setText(NAME); 
     email.setText(EMAIL); 
+2

Das verwendet keine Bindung. Ich weiß, wie das geht. Aber danke. – RogerParis

0
  • Bearbeiten Sie Ihre gradle zu aktualisierende Datei com.android.Unterstützung Bibliotheken zu Version 23.1.1 oder darüber hinaus.

  • Verwenden Sie navigationView.getHeaderView(i), wobei i der Index der headerview ist. Wenn Sie diese Ansicht im Layout definiert haben, lautet sie 0.

0

Ich habe Werkzeuge von Android sdk Manager Build aktualisiert, dann 23.1.0 ist auch für mich gut funktioniert.

Ich benutze buildToolsVersion "23.0.2" Vor diesem war es 23.0.1.

und es besteht keine Notwendigkeit der Verwendung:

(View) navigationView.findViewById(R.id.idOfViewFromHeaderView); 

In Ihrer Tätigkeit können Sie direkt verwenden:

(View) findViewById(R.id.idOfViewFromHeaderView); 
8
ImageView imageView = (ImageView) navigationView.getHeaderView(0).findViewById(R.id.imageButton); 

imageView.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 

     if (flag) { 
      navigationView.getMenu().clear(); //clear old inflated items. 
      navigationView.inflateMenu(R.menu.drawer_view1); 
      flag = false; 
     } else { 
      navigationView.getMenu().clear(); //clear old inflated items. 
      navigationView.inflateMenu(R.menu.drawer_view); 
      flag = true; 
     } 
    } 
}); 
-1

Es funktioniert für mich.

MainActivity.java:

NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); 

    NavHeaderMainBinding binding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.nav_header_main, navigationView, false); 

    navigationView.addHeaderView(binding.getRoot()); 

activity_main.xml:

<android.support.v4.widget.DrawerLayout 
    android:id="@+id/drawer_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:fitsSystemWindows="true" 
    tools:openDrawer="start"> 

    <RelativeLayout 
     android:id="@+id/content_frame" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <android.support.design.widget.AppBarLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content"> 

      <include layout="@layout/toolbar" /> 

     </android.support.design.widget.AppBarLayout> 

    </RelativeLayout> 

    <android.support.design.widget.NavigationView 
     android:id="@+id/nav_view" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:layout_gravity="start" 
     android:fitsSystemWindows="true" 
     app:menu="@menu/activity_main_drawer" /> 

</android.support.v4.widget.DrawerLayout> 

nav_header.xml:

<layout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto"> 

<data> 

    <variable 
     name="account" 
     type="lonja.dreamteam.su.trainingdiary.view_model.AccountViewModel"/> 

</data> 

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="@dimen/nav_header_height" 
    android:background="@drawable/header_background" 
    android:gravity="bottom" 
    android:orientation="vertical" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    android:theme="@style/ThemeOverlay.AppCompat.Dark"> 

    <de.hdodenhof.circleimageview.CircleImageView 
     android:id="@+id/imageView" 
     android:layout_width="72dp" 
     android:layout_height="72dp" 
     android:src="@{account.sex}" 
     app:civ_border_color="@color/colorAccent" 
     app:civ_border_width="0dp" /> 

    <TextView 
     android:id="@+id/userName" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:paddingTop="@dimen/nav_header_vertical_spacing" 
     android:text="@{account.name}" 
     android:textAppearance="@style/TextAppearance.AppCompat.Body1" /> 

</LinearLayout> 

+3

Sie müssen beschreiben, was Sie getan haben nicht nur Postleitzahl ... in der Bemühung, den Nutzen für andere zu maximieren –

+0

Es hilft mir auch – Herry

11

Ich habe eine etwas sauberere Lösung, wo ich Fragment/Aktivität nicht mit Code verseuchen muss, der für das Aufblasen und Hinzufügen der Header-Ansicht zu NavigationView verantwortlich ist. Ich habe die Erweiterungsklasse für NavigationView implementiert. Ich habe das wie folgt aus:

Layout meiner Aktivität:

<data> 
    <variable 
     name="dashboard" 
     type="ramps.view.model.DashboardScreenViewModel"/> 
</data> 

<android.support.v4.widget.DrawerLayout 
    android:id="@+id/drawer_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:fitsSystemWindows="true" 
    tools:openDrawer="start"> 

    <include 
     layout="@layout/activity_dashboard" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     bind:dashboard="@{dashboard}" 
     /> 

    <android.support.design.widget.NavigationView 
     android:id="@+id/nav_view" 
     android:background="@color/white" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:layout_gravity="start" 
     android:fitsSystemWindows="true" 
     app:navigationItemSelectedListener="@{dashboard.onMenuItemSelected}" 
     app:model="@{dashboard.score}" 
     app:menu="@menu/activity_main_drawer"/> 

</android.support.v4.widget.DrawerLayout> 

Wie Sie sehen können, gibt es keine App: headerLayout in NavigationView, aber ich habe meine Gewohnheit hinzugefügt App: Modell, mit Daten, die ich an das Header-Layout übergeben möchte. Wie habe ich diesen benutzerdefinierten Parameter definiert? Nach Erweiterung Klasse:

public class NavigationViewExtensions { 

@BindingAdapter({"bind:model"}) 
public static void loadHeader(NavigationView view, ScoreViewModel model) { 
    ViewNavigationHeaderBinding binding = ViewNavigationHeaderBinding.inflate(LayoutInflater.from(view.getContext())); 
    binding.setScore(model); 
    binding.executePendingBindings(); 
    view.addHeaderView(binding.getRoot()); 
    } 
} 

Platzieren Sie diese Klasse einfach irgendwo in Ihrem Projekt. Und das Layout meiner Header:

<layout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:bind="http://schemas.android.com/apk/res-auto" 
> 

<data> 

    <import type="android.view.View"/> 

    <variable 
     name="score" 
     type="ramps.view.model.ScoreViewModel"/> 
</data> 

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:background="@color/graphite" 
    android:gravity="bottom" 
    android:orientation="vertical" 
    android:paddingBottom="@dimen/activity_vertical_margin_large" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin_large" 
    android:theme="@style/ThemeOverlay.AppCompat.Dark"> 

    <include 
     android:id="@+id/player_details_header_score" 
     layout="@layout/view_avatar_score_header" 
     bind:score="@{score}"/> 

</LinearLayout> 

+0

Diese Antwort sollte Antwort angenommen werden. Ausgezeichneter Beitrag. – Mussa

4

Wenn Sie setzen app:headerLayout="@layout/drawer_header dann müssen Sie nicht wieder den Blick aufzublasen. Sie können einfach .bind anstelle von .inflate verwenden.

Sie können die bereits aufgeblasenen Kopfsicht bekommen und es so binden:

View headerView = binding.navigationView.getHeaderView(0); 
DrawerHeaderBinding headerBinding = DrawerHeaderBinding.bind(headerView); 
+1

Dies ist wahrscheinlich die einfachste Lösung. –

1

Versuchen Sie dies mit Databinding Bibliothek es für mich funktioniert.

navigation_view_header.xml:

<layout xmlns:android="http://schemas.android.com/apk/res/android"> 
<RelativeLayout 
    android:layout_width="match_parent" 
    android:layout_height="@dimen/navigation_view_header_height" 
    android:paddingLeft="@dimen/navigation_view_padding" 
    android:paddingTop="@dimen/navigation_view_top_padding" 
    android:background="@color/colorPrimary"> 


    <ImageView 
     android:id="@+id/avatar" 
     android:layout_width="@dimen/avatar_dimen" 
     android:layout_height="@dimen/avatar_dimen" 
     android:contentDescription="@null" 
     android:src="@drawable/default_avatar" /> 

    <TextView 
     android:id="@+id/profile_email" 
     android:layout_width="match_parent" 
     android:layout_height="48dp" 
     android:layout_below="@+id/avatar" 
     android:text="email" 
     android:textColor="@color/white" 
     android:layout_alignParentBottom="true" 
     android:gravity="center_vertical" /> 

</RelativeLayout> 
</layout> 

activity_main.xml:

<layout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto"> 
    <data> 
     <variable 
      name="navigationItemSelectedListener" 
      type="com.example.MainActivity"/> 
    </data> 
<android.support.v4.widget.DrawerLayout 
    android:id="@+id/drawer_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:fitsSystemWindows="true" 
    android:tag="layout"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="vertical"> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/my_toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      app:titleTextColor="@color/white" 
      android:background="@color/colorPrimary" 
      app:theme="@style/Toolbar.Theme" 
      app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> 

     <FrameLayout 
      android:id="@+id/fragment_container" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" /> 
    </LinearLayout> 

    <android.support.design.widget.NavigationView 
     android:id="@+id/navigation_view" 
     android:layout_width="@dimen/navigation_view_width" 
     android:layout_height="match_parent" 
     android:layout_gravity="start" 
     android:fitsSystemWindows="true" 
     app:theme="@style/Theme.AppCompat.Light" 
     app:menu="@menu/drawer_menu" 
     app:navigationItemSelectedListener="@{navigationItemSelectedListener::onNavigationItemSelected}"/> 

</android.support.v4.widget.DrawerLayout> 
</layout> 

und innerhalb Ihrer Aktivität:

ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, 
       R.layout.activity_main); 
activityMainBinding.setNavigationItemSelectedListener(this);/* with this line navigation menu item selection events are handled in onNavigationItemSelected() specified in navigation_view_header.xml*/ 

NavigationViewHeaderBinding navigationViewHeaderBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.navigation_view_header,activityMainBinding.navigationView,false); 
     activityMainBinding.navigationView.addHeaderView(navigationViewHeaderBinding.getRoot()); 

und stellen Sie sicher, dass Ihre Tätigkeit Geräte NavigationView.OnNavigationItemSelectedListener

1

Ziemlich einfache Lösung hier. Nehmen wir an, Sie hinzugefügt Ihre NavigationView als

<android.support.design.widget.NavigationView 
    android:id="@+id/navigationView" 
    android:layout_width="wrap_content" 
    android:layout_height="match_parent" 
    android:layout_gravity="start" 
    android:fitsSystemWindows="true" 
    app:headerLayout="@layout/nav_drawer_header" 
    app:menu="@menu/menu_nav_drawer"/> 

Und das Sie eine Textview in nav_drawer_header.xml zuzugreifen, die eine ID von textView2 hat. Sie würden also nur diesen Code in Ihrer Tätigkeit nutzen:

View headerContainer = navigationView.getHeaderView(0); // This returns the container layout in nav_drawer_header.xml (e.g., your RelativeLayout or LinearLayout) 
TextView textView2 = (TextView)headerContainer.findViewById(R.id.textView2); 
textView2.setText("Sorted!"); 

Keine Notwendigkeit aufzublasen oder mit Ihrem vorhandenen Code stören usw.