I keep getting an InflateException upon trying to inflate a view in my MenuAdapter
class. I've surrounded the troublesome code in a try-catch block and get the error Message:
link to the entire project:
https://docs.google.com/file/d/0B2Iwl4UysxOMa3E5a1l2SHZwOG8/edit?usp=sharing
Binary XML file line #1: Error inflating class
Here is the code:
package com.example.sidemenututorial;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class MenuListAdapter extends BaseAdapter {
// Fields -----------------------------------------------------------------
private Context context;
private String[] titles;
private String[] subtitles;
private int[] icons;
private LayoutInflater inflater;
// Constructor ------------------------------------------------------------
public MenuListAdapter(
Context context,
String[] titles,
String[] subtitles,
int[] icons){
this.context = context;
this.titles = titles;
this.subtitles = subtitles;
this.icons = icons;
inflater = (LayoutInflater)context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
// Accessors --------------------------------------------------------------
@Override
public int getCount(){
return titles.length;
}
@Override
public Object getItem(int position){
return titles[position];
}
@Override
public long getItemId(int position){
return position;
}
// Methods ----------------------------------------------------------------
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder viewHolder;
// Only inflate the view if convertView is null
if (convertView == null){
viewHolder = new ViewHolder();
convertView = inflater.inflate(
R.layout.drawer_list_item, parent, false);
viewHolder.txtTitle = (TextView)convertView.findViewById(
R.id.title);
viewHolder.txtSubtitle = (TextView)convertView.findViewById(
R.id.subtitle);
viewHolder.imgIcon = (ImageView)convertView.findViewById(
R.id.icon);
// This is the first time this view has been inflated,
// so store the view holder in its tag fields
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder)convertView.getTag();
}
// Set the views fields as needed
viewHolder.txtTitle.setText(titles[position]);
viewHolder.txtSubtitle.setText(subtitles[position]);
viewHolder.imgIcon.setImageResource(icons[position]);
return convertView;
}
// Classes ----------------------------------------------------------------
static class ViewHolder {
TextView txtTitle;
TextView txtSubtitle;
ImageView imgIcon;
}
}
And here is the view it is trying to inflate, the drawer_list_item.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:color/darker_gray"
android:orientation="horizontal"
style="?attr/dropdownListPreferredItemHeight" >
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:adjustViewBounds="true"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical|left"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
style="?attr/spinnerDropDownItemStyle"/>
<TextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceSmall"
style="?attr/spinnerDropDownItemStyle"/>
</LinearLayout>
</LinearLayout>
And here is the client code that is calling the menu adapter:
package com.example.sidemenututorial;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
public class MainActivity extends SherlockFragmentActivity {
// Fields -----------------------------------------------------------------
private DrawerLayout drawerLayout;
private ListView drawerList;
private ActionBarDrawerToggle drawerToggle;
private MenuListAdapter menuAdapter;
private int[] icons;
private Fragment fragment1;
private Fragment fragment2;
private Fragment fragment3;
private CharSequence drawerTitle;
private CharSequence title;
private final String[] titles = new String[]{
"Title Fragment #1",
"Title Fragment #2",
"Title Fragment #3"
};
private final String[] subtitles = new String[]{
"Subtitle Fragment #1",
"Subtitle Fragment #2",
"Subtitle Fragment #3"
};
// Lifecycle Callbacks ----------------------------------------------------
@Override
protected void onCreate(Bundle savedInstanceState) {
// Base implemenation
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Instantiate the fragments
fragment1 = new Fragment1();
fragment2 = new Fragment2();
fragment3 = new Fragment3();
// Get the title from this activity
title = drawerTitle = getTitle();
// Get the icons from the drawables folder
icons = new int[]{
R.drawable.action_about,
R.drawable.action_settings,
R.drawable.collections_cloud
};
// Get the drawer layout from the XML file and the ListView inside it
drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
drawerList = (ListView)findViewById(R.id.listview_drawer);
// Set a custom shadow over that overlays the main content
// when the drawer opens
drawerLayout.setDrawerShadow(
R.drawable.drawer_shadow, GravityCompat.START);
// Pass the string arrays to the MenuListAdapter, set the drawer
// list adapter to it and set up its click listener
menuAdapter = new MenuListAdapter(
MainActivity.this, titles, subtitles, icons);
drawerList.setAdapter(menuAdapter);
drawerList.setOnItemClickListener(new DrawerItemClickListener());
// Enable the action bar to have up navigation
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Allow the the action bar to toggle the drawer
drawerToggle = new ActionBarDrawerToggle(
this,
drawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open,
R.string.drawer_close){
public void onDrawerClosed(View view){
super.onDrawerClosed(view);
}
public void onDrawerOpened(View view){
getSupportActionBar().setTitle(drawerTitle);
super.onDrawerOpened(view);
}
};
drawerLayout.setDrawerListener(drawerToggle);
// If this is the first time opening this activity,
// start with loading fragment #1
if (savedInstanceState == null){
selectItem(0);
}
}
// Methods ----------------------------------------------------------------
@Override
public boolean onOptionsItemSelected(MenuItem item){
// If the user has pressed the action bar icon
if (item.getItemId() == android.R.id.home){
// If the drawer is open, close it; vice versa
if (drawerLayout.isDrawerOpen(drawerList)){
drawerLayout.closeDrawer(drawerList);
} else {
drawerLayout.openDrawer(drawerList);
}
}
// Finish by letting the super class do the rest
return super.onOptionsItemSelected(item);
}
@Override
protected void onPostCreate(Bundle savedInstanceState){
// Call the super implementation and synchronize the drawer
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig){
// Call the super implemenation on this activity
// and the drawer toggle object
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
private void selectItem(int position){
// Create a new fragment transaction and start it
FragmentTransaction fragTran = getSupportFragmentManager()
.beginTransaction();
// Locate the position selected replace the content view
// with the fragment of the number selected
switch (position){
case 0:{
fragTran.replace(R.id.content_frame, fragment1);
break;
}
case 1:{
fragTran.replace(R.id.content_frame, fragment2);
break;
}
case 2:{
fragTran.replace(R.id.content_frame, fragment3);
break;
}
}
// Commit the transaction and close the drawer
fragTran.commit();
drawerList.setItemChecked(position, true);
drawerLayout.closeDrawer(drawerList);
}
public void setTitle(CharSequence title){
// Save the passed in title and set the action bar title
this.title = title;
getSupportActionBar().setTitle(title);
}
// Classes ----------------------------------------------------------------
private class DrawerItemClickListener
implements ListView.OnItemClickListener{
@Override
public void onItemClick(
AdapterView<?> parent,
View view,
int position,
long id) {
// When clicked, select open the appropriate fragment
selectItem(position);
}
}
}
And a log of the crash:
09-26 16:45:43.081: D/AndroidRuntime(1121): Shutting down VM
09-26 16:45:43.081: W/dalvikvm(1121): threadid=1: thread exiting with uncaught exception (group=0x409961f8)
09-26 16:45:45.561: E/AndroidRuntime(1121): FATAL EXCEPTION: main
09-26 16:45:45.561: E/AndroidRuntime(1121): java.lang.NullPointerException
09-26 16:45:45.561: E/AndroidRuntime(1121): at com.example.sidemenututorial.MenuListAdapter.getView(MenuListAdapter.java:73)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.AbsListView.obtainView(AbsListView.java:2033)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.ListView.makeAndAddView(ListView.java:1772)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.ListView.fillDown(ListView.java:672)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.ListView.fillFromTop(ListView.java:732)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.ListView.layoutChildren(ListView.java:1625)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.AbsListView.onLayout(AbsListView.java:1863)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.View.layout(View.java:11180)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.ViewGroup.layout(ViewGroup.java:4203)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:672)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.View.layout(View.java:11180)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.ViewGroup.layout(ViewGroup.java:4203)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.View.layout(View.java:11180)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.ViewGroup.layout(ViewGroup.java:4203)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.LinearLayout.onLayout(LinearLayout.java:1399)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.View.layout(View.java:11180)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.ViewGroup.layout(ViewGroup.java:4203)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.View.layout(View.java:11180)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.ViewGroup.layout(ViewGroup.java:4203)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1468)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2418)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.os.Handler.dispatchMessage(Handler.java:99)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.os.Looper.loop(Looper.java:137)
09-26 16:45:45.561: E/AndroidRuntime(1121): at android.app.ActivityThread.main(ActivityThread.java:4340)
09-26 16:45:45.561: E/AndroidRuntime(1121): at java.lang.reflect.Method.invokeNative(Native Method)
09-26 16:45:45.561: E/AndroidRuntime(1121): at java.lang.reflect.Method.invoke(Method.java:511)
09-26 16:45:45.561: E/AndroidRuntime(1121): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
09-26 16:45:45.561: E/AndroidRuntime(1121): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
09-26 16:45:45.561: E/AndroidRuntime(1121): at dalvik.system.NativeStart.main(Native Method)
09-26 16:45:45.593: D/dalvikvm(1121): GC_CONCURRENT freed 191K, 3% free 14296K/14599K, paused 12ms+8ms
When u get Error inflating your class you have to look for the problem in your XML first.
In your case the problem is in your drawer_list_item layout. In your linearLayout root the "?" character causing it with android:background="?android:color/darker_gray" row.
Use a ViewHolder
http://developer.android.com/training/improving-layouts/smooth-scrolling.html
Change your getView to
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder vh;
if(convertView==null)
{
vh = new ViewHolder();
convertView = inflater.inflate(
R.layout.drawer_list_item, parent, false);
vh.txtTitle = (TextView) convertView.findViewById(R.id.title);
vh.txtSubtitle = (TextView) convertView.findViewById(R.id.subtitle);
vh.imgIcon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(vh);
} else {
vh = (ViewHolder) convertView.getTag();
}
vh.txtTitle.setText(titles[position]);
vh.txtSubtitle.setText(subtitles[position]);
vh.imgIcon.setImageResource(icons[position]);
return convertView;
}
static class ViewHolder
{
TextView txtTitle,txtSubtitle;
ImageView imgIcon;
}
Also move the below to constructor. Declare this as a class member LayoutInflater inflater
In your constructor
inflater = (LayoutInflater)context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
Edit:
In drawer_list_item.xml
Change
android:background="?android:color/darker_gray"
to
android:background="@android:color/darker_gray"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With