I am trying to make an android app with custom spinner with image icons for every item in list. This spinner will show up in the action bar of the app. I am using android-support-v7-appcompat library to make sure action bars show up in android 2.2 and up.
Every thing works fine when I run the app in android 3.0 and up. But the app crashes as soon as I click the spinner in android 2.2 and 2.3. Seems like the spinner is not inflating properly.
Here is my error log for android 2.3 :
02-09 13:55:12.289: E/AndroidRuntime(8624): FATAL EXCEPTION: main
02-09 13:55:12.289: E/AndroidRuntime(8624): java.lang.NullPointerException
02-09 13:55:12.289: E/AndroidRuntime(8624): at android.support.v7.internal.widget.ListPopupWindow$DropDownListView.measureHeightOfChildrenCompat(ListPopupWindow.java:1317)
02-09 13:55:12.289: E/AndroidRuntime(8624): at android.support.v7.internal.widget.ListPopupWindow.buildDropDown(ListPopupWindow.java:1062)
02-09 13:55:12.289: E/AndroidRuntime(8624): at android.support.v7.internal.widget.ListPopupWindow.show(ListPopupWindow.java:514)
02-09 13:55:12.289: E/AndroidRuntime(8624): at android.support.v7.internal.widget.SpinnerICS$DropdownPopup.show(SpinnerICS.java:758)
02-09 13:55:12.289: E/AndroidRuntime(8624): at android.support.v7.internal.widget.SpinnerICS.performClick(SpinnerICS.java:443)
02-09 13:55:12.289: E/AndroidRuntime(8624): at android.view.View$PerformClick.run(View.java:9080)
02-09 13:55:12.289: E/AndroidRuntime(8624): at android.os.Handler.handleCallback(Handler.java:587)
02-09 13:55:12.289: E/AndroidRuntime(8624): at android.os.Handler.dispatchMessage(Handler.java:92)
02-09 13:55:12.289: E/AndroidRuntime(8624): at android.os.Looper.loop(Looper.java:130)
02-09 13:55:12.289: E/AndroidRuntime(8624): at android.app.ActivityThread.main(ActivityThread.java:3687)
02-09 13:55:12.289: E/AndroidRuntime(8624): at java.lang.reflect.Method.invokeNative(Native Method)
02-09 13:55:12.289: E/AndroidRuntime(8624): at java.lang.reflect.Method.invoke(Method.java:507)
02-09 13:55:12.289: E/AndroidRuntime(8624): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
02-09 13:55:12.289: E/AndroidRuntime(8624): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
02-09 13:55:12.289: E/AndroidRuntime(8624): at dalvik.system.NativeStart.main(Native Method)
I used made these two classes to make the custom spinner:
1) SpinnerNavItem.java :
package com.hpubts50.hpubustracker.model;
public class SpinnerNavItem {
private String title;
private int icon;
public SpinnerNavItem(String title, int icon){
this.title = title;
this.icon = icon;
}
public String getTitle(){
return this.title;
}
public int getIcon(){
return this.icon;
}
}
2) BusNavigation.java - its a adapter class :
package com.hpubts50.hpubustracker.adapter;
import java.util.ArrayList;
import android.content.Context;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.hpubts50.hpubustracker.R;
import com.hpubts50.hpubustracker.model.SpinnerNavItem;
public class BusNavigation extends BaseAdapter {
private ImageView busIcon;
private TextView busTitle;
private ArrayList<SpinnerNavItem> spinnerNavItem;
private Context context;
public BusNavigation(Context context, ArrayList<SpinnerNavItem> spinnerNavItem) {
this.spinnerNavItem = spinnerNavItem;
this.context = context;
}
@Override
public int getCount() {
return spinnerNavItem.size();
}
@Override
public Object getItem(int index) {
return spinnerNavItem.get(index);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(ActionBarActivity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.bus_names, null);
}
busIcon = (ImageView) convertView.findViewById(R.id.busIcon);
busTitle = (TextView) convertView.findViewById(R.id.busTitle);
busIcon.setImageResource(spinnerNavItem.get(position).getIcon());
busIcon.setVisibility(View.GONE);
busTitle.setText(spinnerNavItem.get(position).getTitle());
return convertView;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(ActionBarActivity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.bus_names, null);
}
busIcon = (ImageView) convertView.findViewById(R.id.busIcon);
busTitle = (TextView) convertView.findViewById(R.id.busTitle);
busIcon.setImageResource(spinnerNavItem.get(position).getIcon());
busTitle.setText(spinnerNavItem.get(position).getTitle());
return convertView;
}
}
and here is my MainActivity.java :
package com.hpubts50.hpubustracker;
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.OnNavigationListener;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.widget.Toast;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.hpubts50.hpubustracker.adapter.BusNavigation;
import com.hpubts50.hpubustracker.model.SpinnerNavItem;
public class MainActivity extends ActionBarActivity implements OnNavigationListener {
GoogleMap BusMap;
private ActionBar actionBar;
private ArrayList<SpinnerNavItem> navSpinner;
private BusNavigation busAdapter;
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Configuring Action Bar to support list adapter
showListView();
// Converting values to pixels from density pixels
final int paddingUP_dp = 60;
final int paddingDOWN_dp = 70;
final float scale = getResources().getDisplayMetrics().density;
int paddingUP_px = (int) (paddingUP_dp * scale + 0.5f);
int paddingDOWN_px = (int) (paddingDOWN_dp * scale + 0.5f);
// Changing positions for the map zoom controls and compass
BusMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.bus_map)).getMap();
BusMap.setPadding(0, paddingUP_px, 0, paddingDOWN_px);
}
private void showListView() {
actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
navSpinner = new ArrayList<SpinnerNavItem>();
navSpinner.add(new SpinnerNavItem("All", R.drawable.ic_action_about));
navSpinner.add(new SpinnerNavItem("Nandi", R.drawable.ic_action_about));
navSpinner.add(new SpinnerNavItem("Alaknanda", R.drawable.ic_action_about));
navSpinner.add(new SpinnerNavItem("Other Buses", R.drawable.ic_action_about));
busAdapter = new BusNavigation(getApplicationContext(), navSpinner);
actionBar.setListNavigationCallbacks(busAdapter, this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
switch (itemPosition) {
case 1:
Toast.makeText(getApplicationContext(), "Its Working ...", Toast.LENGTH_SHORT).show();
break;
}
return false;
}
}
I have followed this tutorial to make this custom spinner : tutorial link