2017-06-09 1 views
1

Seit ich begann, die Erben von Android Views zu erstellen, sehe ich häufig den Fehler Binary XML file line XX: Error inflating class. In diesem speziellen Fall wird es die BottomSheet sein.Binäre XML-Dateizeile XX: Fehler beim Aufblasen der Klasse Beim Vererben der BottomSheet

public class MyBottomSheet extends TableLayout { 

    BottomSheetBehavior myBottomSheetBehavior; 
    ImageView testImageView; 

    public MyBottomSheet(Context context, AttributeSet attributeSet) { 
     super(context, attributeSet); 

     testImageView = (ImageView) findViewById(R.id.imageView); // still OK... 

     myBottomSheetBehavior = BottomSheetBehavior.from(this); // crashes Here 
     testImageView.setOnClickListener(onClickListener); // or here if to remove the previous row 

    } 

    // ... 
} 

Meine App verfügt über mehrere Registerkarten mit einzelnen Fragmenten. Die BottomSheet erfordert nur in einer von ihnen, aber wenn ich die BottomSheet in der MainActivity Markup nicht enthalten, wird es nicht verschieben. So ist der Code:

activity_main.xml

<?xml version="1.0"encoding="utf-8"?> 
<android.support.v4.widget.DrawerLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/drawer_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:fitsSystemWindows="true"> 

    <android.support.design.widget.CoordinatorLayout 
    android:id="@+id/coordinatorLayout" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 

    <!-- ... --> 

     <include layout="@layout/my_bottom_sheet"/> 
    </android.support.design.widget.CoordinatorLayout> 
</android.support.v4.widget.DrawerLayout> 

my_bottom_sheet.xml

<?xml version="1.0" encoding="utf-8"?> 
<com.example.bottomsheettest.widgets.MyBottomSheet 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/myBottomSheet" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:stretchColumns="*" 
    tools:context="com.example.bottomsheettest.MainActivityFragment" 
    tools:showIn="@layout/activity_main"> 

    <TableRow> 
     <ImageView 
      android:id="@+id/imageView" 
      android:src="@mipmap/ic_launcher" 
      android:layout_height="wrap_content" 
      android:layout_width="wrap_content" 
      /> 
    </TableRow> 

</com.example.bottomsheettest.widgets.MyBottomSheet> 

MainActivityFragment.java

public class MainActivityFragment extends Fragment { 

    private static final int LAYOUT = R.layout.fragment_main; 
    private MainViewFAB fab; 
    private MyBottomSheet addNewItemToInboxBottomSheet; 

    public MainActivityFragment() { 

    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

     MainActivity activity = (MainActivity)getActivity(); 
     fab = activity.getMainViewFab(); 

     addNewItemToInboxBottomSheet = (MyBottomSheet) activity.findViewById(R.id.myBottomSheet); 

     return inflater.inflate(LAYOUT, container, false); 

    } 
} 

Ich nehme an, ich habe etwas wichtiges über Android Views Vererbung verpasst. Aber dieser Fall ist besonders seltsam. In der MyBottomSheet Klasse gibt es kein Problem, wenn Sie die ImageView von der BottomSheet bekommen. Somit steht der Zugriff auf BottomSheet aus der jeweiligen Klasse zur Verfügung. Jedoch, wenn versuchen, etwas zu manipulieren, das mit BottomSheet verwandt ist, wird die Ausnahme sein.


Ich teile die source code (.zip) im Android Studio erstellt während der eine Antwort zu akzeptieren. In der freigegebenen App gibt es keine Tabs, die Fragmentstruktur wurde jedoch beibehalten, da sie in der ursprünglichen App vorhanden ist.

+0

Nun, der 'setOnClickListener()' Aufruf auf dem 'ImageView' stürzt ab, weil er noch nicht im Konstruktor zu Ihrer benutzerdefinierten' View' hinzugefügt wurde. Sie können dies stattdessen in 'onFinishInfllate()' tun.Was ist der Fehler für den BottomSheetBehavior-Absturz? –

+0

Oh, tatsächlich, ich glaube, das wird abstürzen, weil Ihre benutzerdefinierte 'Ansicht' ihre' LayoutParams' noch nicht im Konstruktor hat, und 'BottomSheetBehavior.from()' wird eine 'IllegalArgumentException' auslösen. Das solltest du auch in 'onFinishInfllate()' können. –

+0

@Mike M: Der Fehler ist in beiden Fällen "BottomSheetBehavior" und "Listener" gleich: 'android.view.InflateException: Binär XML-Datei Zeile # 31' (ja, bis zur Nummer der Zeile). Ich werde die Theorie über 'LayoutParams' überprüfen und erneut schreiben. –

Antwort

1

Beim Erstellen einer View Unterklasse, die aus einem Layout heraus aufgeblasen werden soll, gibt es einige Dinge, die zur Laufzeit nicht im Konstruktor verfügbar sind.

Zum einem Kind View s Ihrer benutzerdefinierten View im Layout definiert wird noch nicht aufgeblasen und angebracht worden war, so dass jeder Versuch, Verweise auf sich mit findViewById() zu bekommen null dorthin zurückkehren. Stattdessen sollte dies nicht früher als onFinishInflate() erfolgen, und das Verschieben Ihrer ImageView Initialisierung zu dieser Methode löst diesen bestimmten Fehler.

Auch Ihre benutzerdefinierte View selbst hat keine eigenen LayoutParams Set noch im Konstruktor. Dies verursacht das Problem mit der BottomSheetBehavior.from() Aufruf dort, da diese Methode einfach die Behavior aus der LayoutParams erstellt während der Inflation von Layout-Attribute auf der View abgerufen. In der onAttachedToWindow() Methode wurde die LayoutParams festgelegt, und Sie können den BottomSheetBehavior.from() Anruf dort machen.

Schließlich möchte ich nur erwähnen, dass ein InflateException geworfen wird, wenn irgendetwas mit der Inflation schief geht. Die Grundursache für den Fehler wird im Stack-Trace weiter unten aufgeführt, und Sie sollten dort nach den relevanteren Details suchen.

+1

Danke für die Erklärungen! Ich brauchte es für tiefes Verständnis. –

Verwandte Themen