Can someone point out what's the problem with this code snippet
Custom adapter
public class NavigationAdapter extends ArrayAdapter<NavItem> {
private Context context;
private NavItem[] values;
public NavigationAdapter(Context context, int layoutResourceId,NavItem[] values) {
super(context, layoutResourceId);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final Holder holder;
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View convertView1 = convertView;
if (convertView1 == null) {
holder = new Holder();
convertView1 = vi.inflate(R.layout.item_row, parent,false);
holder.imageView = (ImageView) convertView1.findViewById(R.id.rowIcon);
holder.textView = (TextView) convertView1.findViewById(R.id.rowText);
convertView1.setTag(holder);
} else {
holder = (Holder) convertView1.getTag();
}
NavItem item = values[position];
holder.imageView.setImageResource(item.icon);
holder.textView.setText(item.name);
return convertView1;
}
private class Holder {
public TextView textView;
public ImageView imageView;
}
}
custom listview layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:padding ="10dp">
<ImageView
android:id="#+id/rowIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:src="#drawable/ic_action_settings"
android:paddingRight="10dp"/>
<TextView
android:id="#+id/rowText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/rowIcon"
android:paddingRight="10dp"
android:textAppearance="?android:attr/textAppearanceListItemSmall"/>
Main activity
NavItem settings = new NavItem();
settings.icon = R.drawable.ic_action_settings;
settings.name = "Settings";
NavItem send = new NavItem(R.drawable.ic_action_settings,"Sent");
NavItem[] values = new NavItem[]{
settings,send
};
NavigationAdapter adapter = new NavigationAdapter(this, R.layout.item_row, values);
mDrawerListView.setAdapter(adapter);
When I open the drawer it just shows a blank page. If I change the adapter to ArrayAdapter of string and inflate the built in layout then it works, but I want to add image next to the text.
I have faced similar problem in my experience.
I solved this problem by changing :
public class NavigationAdapter extends ArrayAdapter<NavItem> {
}
to :
public class NavigationAdapter extends BaseAdapter<NavItem> {
}
I have extended my custom adapter from BaseAdapter class which have worked for my case. Please try this if it works for you also
Related
I'm trying to customize ListView to show a list of images so i wrote the following code but unfortunately its not working.
layout/menu.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:background="#drawable/menu_bg">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/name"
android:layout_gravity="center"/>
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/menu_list"
android:layout_gravity="center"
android:layout_marginTop="60sp"></ListView>
</LinearLayout>
layout/menu_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/item"/>
</LinearLayout>
Menu.java
public class Menu extends Activity{
private int[] items = {R.drawable.res_opt, R.drawable.new_game_opt, R.drawable.score_opt, R.drawable.exit_opt};
ListView list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
list = (ListView) findViewById(R.id.menu_list);
list.setAdapter(new MenuAdapter(Menu.this, items));
}
}
MenuAdapter.java
public class MenuAdapter extends ArrayAdapter{
private int[] items;
private Context context;
public MenuAdapter(Context context, int[] items) {
super(context, R.layout.menu_item);
this.context = context;
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//make sure we have a view to work with
View itemView = convertView;
if(itemView == null)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
itemView = inflater.inflate(R.layout.menu_item,null, true);
}
//Find the object to work with
int id = items[position];
//Fill the view
ImageView item = (ImageView) itemView.findViewById(R.id.item);
item.setImageResource(id);
return itemView;
}
}
Add view holder class to your code, as its incomplete.
public class ViewHolder{
public ImageView iv;
}
Now, your code will look like this:
ViewHolder mViewHolder = new ViewHolder();
if(itemView == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
itemView = inflater.inflate(R.layout.menu_item,null, null);
mViewHolder.iv = (ImageView) itemView.findViewById(R.id.item);
itemView.setTag(mViewHolder);
}else{
mViewHolder = (ViewHolder) itemView.getTag();
}
//Find the object to work with
int id = items[position];
//Fill the view
mViewHolder.iv.setImageResource(id);
Also, you have missed adding size for you ListView adapter.
Hope, this could help you.
You need to use another super constuctor of ArrayAdapter.
public class MenuAdapter extends ArrayAdapter<Integer>{
private Integer[] items;
private Context context;
public MenuAdapter(Context context, Integer[] items) {
super(context, R.layout.menu_item, items);
this.context = context;
this.items = items;
}
Edited
Also fix this line
itemView = inflater.inflate(R.layout.menu_item,parent, false);
In my app, I am creating a dynamic list of items using
shopsNameList = new ArrayList<String>();
// Create The Adapter
ArrayAdapter<String> arrayAdapter =
new ArrayAdapter<String>(ShopsListActivity.this, android.R.layout.simple_list_item_1, shopsNameList);
I would like to have a text and an image in each element of the list, not a simple text.
I defined a listviewitem.xml layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/listitemimage"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="#raw/shop" />
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Test" />
</LinearLayout>
and tried
ArrayAdapter<String> arrayAdapter =
new ArrayAdapter<String>(ShopsListActivity.this, R.layout.listviewitem, shopsNameList);
but my app crashes when I enter the list.
I am inside an activity creted with
super.onCreate(saveInstanceState);
setContentView(R.layout.shopslist);
// Get the reference of ListView
ListView shopsList=(ListView)findViewById(R.id.listShops);
shopsNameList = new ArrayList<String>();
shopElements = new ArrayList<ShopElement>();
You need to create custom adapter for your ListView:
public class CustomAdapter extends ArrayAdapter<String>{
Context context;
public CustomAdapter(Context context, List< String > objects)
{
super( context, R.layout.listviewitem, objects );
this.context = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ShopListHolder holder = null;
if(convertView == null)
{
LayoutInflater inflater = LayoutInflater.from( context );
convertView = inflater.inflate(R.layout.listviewitem, parent, false);
holder = new ShopListHolder();
holder.imgIcon = (ImageView)convertView.findViewById(R.id.listitemimage);
holder.txtTitle = (TextView)convertView.findViewById(R.id.textview);
convertView.setTag(holder);
}
else
{
holder = (ShopListHolder )convertView.getTag();
}
holder.txtTitle.setText(getItem( position ));
return convertView;
}
class ShopListHolder
{
ImageView imgIcon;
TextView txtTitle;
}
}
I created my own custom adapter that extends Array Adapter:
public class AdapterGeoArea extends ArrayAdapter<GeoArea>{
private Context _context;
private int resource;
private ArrayList<GeoArea> _myGeoArea;
public AdapterGeoArea(Context context, ArrayList<GeoArea> myGeoArea) {
super(context, 0, myGeoArea);
_context = context;
_myGeoArea = myGeoArea;
}
public int getCount() {
return _myGeoArea.size();
}
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout GeoAreaView;
if (convertView == null) {
GeoAreaView = new LinearLayout(_context);
LayoutInflater li = LayoutInflater.from(_context);
convertView = li.inflate(R.layout.layout_geo_areas, null);
}
else {
GeoAreaView = (LinearLayout) convertView;
}
GeoArea curGeoArea = _myGeoArea.get(position);
TextView name = (TextView) GeoAreaView.findViewById(R.id.txtGeoAreaName);
name.setText(curGeoArea.name);
return convertView;
}
static class ViewHolder {
TextView name;
RelativeLayout childContainer;
}
#Override
public Filter getFilter() {
return null;
}
}
And here is how I am using it in my main:
public class ActivityGeoAreas extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_geo_areas);
GeoArea.searchTerm = "Bar & Grill";
GeoArea torontoArea = new GeoArea("cityOfToronto");
ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
testList.add(torontoArea);
AdapterGeoArea adapter = new AdapterGeoArea(this, testList);
ListView lv = (ListView) findViewById(R.id.textGeoArea);
lv.setAdapter(adapter);
}
}
Everything seem to be fine except for this line:
TextView name = (TextView) GeoAreaView.findViewById(R.id.textGeoArea);
And here is how I defined my layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".ActivityGeoAreas" >
<TextView
android:id="#+id/textGeoArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Choose Area"
android:textAppearance="?android:attr/textAppearanceLarge" />
<LinearLayout
android:id="#+id/LinearLayoutGeoAreas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textGeoArea"
android:layout_below="#+id/textGeoArea"
android:orientation="vertical" >
<ListView
android:id="#+id/listViewGeoArea"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
</ListView>
</LinearLayout>
</RelativeLayout>
It simply can't find the TextView textGeoArea and this line become null, what am I doing wrong?
Change this
TextView name = (TextView) GeoAreaView.findViewById(R.id.txtGeoAreaName);
to
TextView name = (TextView) convertView.findViewById(R.id.txtGeoAreaName);
I guess you have got confused.
Move textview to a new layout list_item.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="match_parent" >
<TextView
android:id="#+id/textGeoArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="14dp"
android:text="Choose Area"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
Now change your getView as below
LayoutInflater inflater;
public AdapterGeoArea(Context context, ArrayList<GeoArea> myGeoArea) {
super(context, 0, myGeoArea);
_context = context;
_myGeoArea = myGeoArea;
inflater = LayoutInflater.from(context); // initialize inflater
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_row,parent,false);
holder = new ViewHolder();
holder.tv = (TextView)convertView.findViewById(R.id.textGeoArea);
holder.setTag(convertView);
}
else {
holder = (ViewHolder) convertView.getTag();
}
GeoArea curGeoArea = _myGeoArea.get(position);
holder.tv.setText(curGeoArea.name);
return convertView;
}
static class ViewHolder // use a view holder for smooth scrolling an performance
{
TextView tv;
}
On the first pass, GeoAreaView is a childless LinearLayout since you just created it. convertView is the View initialized your layout which holds the TextView. So you need to use that to find the TextView.
TextView name = (TextView) convertView.findViewById(R.id.txtGeoAreaName);
I see you have a ViewHolder but you don't appear to be using it. You may want to take a little time and go through a good tutorial on using ListView.
This guy usually seems to have good tutorials
I created this class called GeoArea, which is suppose to store "Geographical Area" that have children Geographical Areas, this is fairly strait foward:
public class GeoArea {
public String id;
public String name;
public List<GeoArea> subGeoAreas;
public GeoArea parentGeoArea;
public GeoArea(String id) {
this.id = id;
name = id;
subGeoAreas = new LinkedList<GeoArea>();
}
#Override
public String toString() {
return name;
}
}
I have created the following Layout to render it on Android, the idea here is to for each GeoArea to recursively render it self and then it's children GeoArea in a listView:
//layout_geo_area.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/txtGeoAreaName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:gravity="left"
android:text="Geo Area Name"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ListView
android:id="#+id/listViewChildGeoAreas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/txtGeoAreaName"
android:gravity="left" >
</ListView>
</RelativeLayout>
This is my adapter I created for GeoArea to be displayed in a listView:
public class AdapterGeoArea extends ArrayAdapter<GeoArea>{
private ArrayList<GeoArea> _myGeoArea;
private Context _myContext;
LayoutInflater _inflater;
public AdapterGeoArea(Context context, ArrayList<GeoArea> myGeoArea) {
super(context, 0, myGeoArea);
_myGeoArea = myGeoArea;
_inflater = LayoutInflater.from(context);
_myContext = context;
}
public int getCount() {
return _myGeoArea.size();
}
public View getView(int position, View convertView, ViewGroup parent) {
GeoAreaLayoutHolder holder;
if (convertView == null) {
convertView = _inflater.inflate(R.layout.layout_geo_area,parent,false);
holder = new GeoAreaLayoutHolder();
holder.txtGeoAreaName = (TextView)convertView.findViewById(R.id.txtGeoAreaName);
holder.txtGeoAreaName.setTag(convertView);
holder.listViewChildGeoAreas = (ListView)convertView.findViewById(R.id.listViewChildGeoAreas);
holder.listViewChildGeoAreas.setTag(convertView);
} else {
holder = (GeoAreaLayoutHolder) convertView.getTag();
}
GeoArea curGeoArea = _myGeoArea.get(position);
holder.txtGeoAreaName.setText(curGeoArea.name);
if(curGeoArea.subGeoAreas.size()>0){
ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
AdapterGeoArea adapter = new AdapterGeoArea(_myContext, testList);
for(GeoArea childGeoArea:curGeoArea.subGeoAreas){
testList.add(childGeoArea);
}
holder.listViewChildGeoAreas.setAdapter(adapter);
}
return convertView;
}
static class GeoAreaLayoutHolder {
public TextView txtGeoAreaName;
public ListView listViewChildGeoAreas;
}
}
And here is my Activity that I am using to set it all up:
public class ActivityGeoAreas extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_geo_area);
GeoArea.searchTerm = "Bar & Grill";
GeoArea torontoArea = new GeoArea("cityOfToronto");
ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
testList.add(torontoArea);
AdapterGeoArea adapter = new AdapterGeoArea(this, testList);
ListView lv = (ListView) findViewById(R.id.listViewChildGeoAreas);
lv.setAdapter(adapter);
}
}
When I try to run it, I get the error nullPointerException on the line:
holder.txtGeoAreaName.setText(curGeoArea.name);
What am I doing wrong?
You may want to check ExpandableListView may suit your needs better
http://developer.android.com/reference/android/widget/ExpandableListView.html
An example # http://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/
Continuing from my previous answer to your question ( i though that solved your problem)
To display just name in your listview
list_row.xml // this is the layout with textview to be inflated in getView.
Each row will have textview
<?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="match_parent" >
<TextView
android:id="#+id/textGeoArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="14dp"
android:text="Choose Area"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
layout_geo_area.xml // with only listview no textview
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/listViewChildGeoAreas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:gravity="left" >
</ListView>
</RelativeLayout>
Now your adapter class
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_row,parent,false);
// inflate list_row.xml with textview
holder = new ViewHolder();
holder.tv = (TextView)convertView.findViewById(R.id.textGeoArea);
holder.setTag(convertView);
}
else {
holder = (ViewHolder) convertView.getTag();
}
GeoArea curGeoArea = _myGeoArea.get(position);
holder.tv.setText(curGeoArea.name);
return convertView;
}
static class ViewHolder // use a view holder for smooth scrolling an performance
{
TextView tv;
}
You have a custom adapter.
public class AdapterGeoArea extends ArrayAdapter<GeoArea>{
Now you set the adapter to listview like below
AdapterGeoArea adapter = new AdapterGeoArea(this, testList);
ListView lv = (ListView) findViewById(R.id.listViewChildGeoAreas);
lv.setAdapter(adapter);
So why do you need the below. remove these
if(curGeoArea.subGeoAreas.size()>0){
ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
AdapterGeoArea adapter = new AdapterGeoArea(_myContext, testList);
for(GeoArea childGeoArea:curGeoArea.subGeoAreas){
testList.add(childGeoArea);
}
holder.listViewChildGeoAreas.setAdapter(adapter);
I'm trying to get my spinneradapter working. I get no error's but
the spinner remains empty. I have read multiple tutorials but they aren't seem to work
very well. I'm trying to turn every row in a specifik color, that's why I need the adapter.
This is my code:
public class spinnerAdapter extends ArrayAdapter<String> implements
SpinnerAdapter {
Context context;
ArrayList<String> dateArray;
public spinnerAdapter(Context context, ArrayList<String>dateArray) {
super(context, R.layout.ruilen2_spinner);
this.context = context;
this.dateArray = dateArray;
}
static class ViewHolder {
public TextView textView;
public TextView textView2;
}
#Override
public View getDropDownView(int position, View view, ViewGroup parent) {
View rowView = view;
final ViewHolder holder;
if (rowView == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
rowView = vi.inflate(R.layout.ruilen2_spinner, null);
holder = new ViewHolder();
holder.textView = (TextView)rowView.findViewById(R.id.spinnerdate);
//holder.textView2 = (TextView)rowView.findViewById(R.id.spinnerworkplace);
rowView.setTag(holder);
}
else{
holder = (ViewHolder) rowView.getTag();
}
holder.textView.setText(dateArray.get(position));
return super.getDropDownView(
position, rowView, parent);
}
}
Here's the code snippet where I call the class:
s.setAdapter(new spinnerAdapter(getParent(),namen));
And last but not least the XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:background="#color/white"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/spinnerdate" android:textColor="#color/black"></TextView>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/spinnerworkplace" android:textColor="#color/black"></TextView>
</LinearLayout>
If it is displaying but is empty then you might not be creating your dateArray properly. Did you check to make sure namen in s.setAdapter(new spinnerAdapter(getParent(),namen)); has anything in it?