I'm trying to create a inflated dialog which contains dynamic amount of items.
These Items I inflate aswell.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
int anzJobViews = getArguments().getInt("param");
View rootView = inflater.inflate(R.layout.dialog_job_chooser, container, false);
//getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
ListView listview = (ListView) rootView.findViewById(R.id.dialog_chooser_listview);
for (int i = 0; i < anzJobViews; i++) {
listview.addFooterView( new JobItemView(context));
Log.i("JobChooser","Item added");
}
return rootView;
}
The View (Contains some simple TextViews)
private void init() {
inflate(getContext(), R.layout.job_item_view, this);
}
When showing the dialog I see Nothing.
The xml layout for the dialog.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:background="#drawable/round_corners_selected"
android:backgroundTint="#color/washedOutGreen">
<ListView
android:id="#+id/dialog_chooser_listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
The Items a want to add to the List.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/blue_focused">
<TextView
android:id="#+id/tv_jobname_area"
android:text="defaultName"
android:layout_margin="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/tv_jobvalue_area"
android:text="0 /h"
android:layout_margin="5dp"
android:layout_toRightOf="#+id/tv_jobname_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
Why don't use an adapter to populate your listview? An example from here: http://www.pcsalt.com/android/listview-using-baseadapter-android/
public MyBaseAdapter(Context context, ArrayList myList) {
this.myList = myList;
this.context = context;
inflater = LayoutInflater.from(this.context);
}
#Override
public int getCount() {
return myList.size();
}
#Override
public ListData getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
MyViewHolder mViewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.layout_list_item, parent, false);
mViewHolder = new MyViewHolder(convertView);
convertView.setTag(mViewHolder);
} else {
mViewHolder = (MyViewHolder) convertView.getTag();
}
ListData currentListData = getItem(position);
mViewHolder.tvTitle.setText(currentListData.getTitle());
mViewHolder.tvDesc.setText(currentListData.getDescription());
mViewHolder.ivIcon.setImageResource(currentListData.getImgResId());
return convertView;
}
private class MyViewHolder {
TextView tvTitle, tvDesc;
ImageView ivIcon;
public MyViewHolder(View item) {
tvTitle = (TextView) item.findViewById(R.id.tvTitle);
tvDesc = (TextView) item.findViewById(R.id.tvDesc);
ivIcon = (ImageView) item.findViewById(R.id.ivIcon);
}
}
}
Also, if you are in a pre kitkat enviroment, you can only use addFooterView before setting the adapter.
Note: When first introduced, this method could only be called before setting the adapter with setAdapter(ListAdapter). Starting with KITKAT, this method may be called at any time. If the ListView's adapter does not extend HeaderViewListAdapter, it will be wrapped with a supporting instance of WrapperListAdapter.
Reference: http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)
use getView function to setup your listview
public View getView (int position, View convertView, ViewGroup list) {
View element;
if (convertView == null) {
element = View.inflate(context, R.layout.items, null);
}
else {
element = convertView;
}
//setup here something
//e.g.
TextView tv = (TextView) v.findViewById(R.id.tv);
tv.setText("myText");
return element;
}
Related
I Created custom grid view with product list based on web service(json).but i facing new issue.when i set size(100dp) for image view height & width it working perfectly.but i set wrap_content or match parent it's view images are blink & blink again..
my fragment class :
public class HorizontalAdapter extends BaseAdapter {
private ArrayList<HomeCategoriesData> mArrayList;
private Context mContext;
private LayoutInflater mLayoutInflater;
public HorizontalAdapter(Activity homeActivity, ArrayList<HomeCategoriesData> mArrayList) {
this.mContext = homeActivity;
this.mArrayList = mArrayList;
mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return mArrayList.size();
}
#Override
public Object getItem(int position) {
return mArrayList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder mViewHolder;
if (convertView == null) {
mViewHolder = new ViewHolder();
convertView = mLayoutInflater.inflate(R.layout.item_categories_item, null);
mViewHolder.mTvName = (TextView) convertView.findViewById(R.id.tv_categories_name);
mViewHolder.mIvimage = (ImageView) convertView.findViewById(R.id.iv_categories_img);
convertView.setTag(mViewHolder);
} else {
mViewHolder = (ViewHolder) convertView.getTag();
}
mViewHolder.mTvName.setText(mArrayList.get(position).getName());
Picasso.with(mContext).load(mArrayList.get(position).getCat_img()).into(mViewHolder.mIvimage);
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext,mArrayList.get(position).getName(),Toast.LENGTH_SHORT).show();
//calling fragment from adatper class...
SellerSubCategoryFragment frag = new SellerSubCategoryFragment();
FragmentManager fm = ((MainActivity)mContext).getSupportFragmentManager();
Bundle bundle = new Bundle();
bundle.putString("id", String.valueOf(mArrayList.get(position).getId()));
frag.setArguments(bundle);
fm.beginTransaction().replace(R.id.content_frame,frag).addToBackStack(null).commit();
}
});
return convertView;
}
private class ViewHolder {
TextView mTvName;
ImageView mIvimage;
}
}
my adapter class xml file :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/iv_categories_img"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
<TextView
android:id="#+id/tv_categories_name"
style="#android:style/TextAppearance.Small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/margin_top_categories_name_5"
android:gravity="center"
android:lines="1"
android:textColor="#color/black" />
</LinearLayout>
my out put issue are ,
so what i do? and what is the problem.why i cannot set wrap_content or match_parent in this grid view?. my custom grid view are ExpandapleHeightGridView
So im new in Android programming I'm trying to make a custom ListView. I follow a tutorial on YouTube (https://www.youtube.com/watch?v=gAIB4fTm2BA) but i cant get it work on a fragment.
public class DriverFragment extends Fragment implements GeneralFragment {
ListView listView;
public DriverFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view;
view = inflater.inflate(R.layout.fragment_driver, container, false);
listView = (ListView) view.findViewById(R.id.driverList);
DriverAdapter driverAdapter = new DriverAdapter(getActivity().getApplicationContext(),R.layout.driver_listview);
listView.setAdapter(driverAdapter);
Driver a = new Driver("John Smith","Johnsmith#example.com","123");
driverAdapter.add(a);
return view;
}
Driver Adapter :
public class DriverAdapter extends ArrayAdapter {
ArrayList list = new ArrayList();
public DriverAdapter(Context context, int resource) {
super(context, resource);
}
static class Holder{
TextView NAME;
TextView EMAIL;
TextView PHONE;
}
public void add(Driver driver) {
list.add(driver);
super.add(driver);
}
#Override
public Object getItem(int position) {
return this.list.get(position);
}
public int getCount(){
return this.list.size();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
row = convertView;
Holder holder;
if(convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.driver_listview, parent, false);
holder = new Holder();
holder.NAME = (TextView) row.findViewById(R.id.driverName);
holder.EMAIL = (TextView) row.findViewById(R.id.driverMail);
holder.PHONE = (TextView) row.findViewById(R.id.driverPhone);
row.setTag(holder);
}else {
holder = (Holder) row.getTag();
}
Driver driver = (Driver)getItem(position);
holder.NAME.setText(driver.getName());
holder.EMAIL.setText(driver.getMail());
holder.PHONE.setText(driver.getPhone());
return row;
}
The XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="DriverName"
android:id="#+id/driverName"
android:padding="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="DriverMail"
android:id="#+id/driverMail"
android:layout_gravity="center_horizontal"
android:padding="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="DriverPhone"
android:id="#+id/driverPhone"
android:padding="10dp" />
first of all if you should really check out some good tutorial like
Using lists in Android (ListView) - Tutorial
http://www.vogella.com/tutorials/AndroidListView/article.html
Assuming everything is okay with your Fragment and it´s visible, lets focus on your Adapter. Since your DriverAdapter has it´s own ArrayList of data there is no point in calling super.add() in it´s add() method. You just call notifyDataSetChanged() to let the Adapter know that it should refresh the content on the UI. Try something like this..
public class DriverAdapter extends BaseAdapter {
ArrayList<Driver> data = new ArrayList();
public void add(Driver driver) {
data.add(driver);
notifyDataSetChanged();
}
public void addAll(List<Driver> drivers) {
data.addAll(drivers);
notifyDataSetChanged();
}
#Override
public Driver getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public int getCount() {
return data.size();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.item_driver_row, parent, false);
holder = new Holder();
holder.name = (TextView) convertView.findViewById(R.id.driverName);
holder.email = (TextView) convertView.findViewById(R.id.driverMail);
holder.phone = (TextView) convertView.findViewById(R.id.driverPhone);
} else {
holder = (Holder) convertView.getTag();
}
Driver driver = getItem(position);
holder.name.setText(driver.getName());
holder.email.setText(driver.getEmail());
holder.phone.setText(driver.getPhone());
convertView.setTag(holder);
return convertView;
}
static class Holder {
TextView name;
TextView email;
TextView phone;
}
}
My last answer didn't seem to help, I quickly put something together.
I would strongly advise reading up more on this topics since Lists and Adapters are an integral part of Android development and having an understanding of how it works is really helpful.
public class Driver {
private String name;
private String email;
private String phone;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
ListView listView = (ListView) view.findViewById(R.id.listView);
Driver a = new Driver();
a.setName("Name");
a.setEmail("Email");
a.setPhone("Phone");
ArrayList<Driver> drivers = new ArrayList<>();
drivers.add(a);
DriverAdapter driverAdapter = new DriverAdapter(getActivity().getApplicationContext(),R.layout.driver_listview, drivers);
listView.setAdapter(driverAdapter);
return view;
}
Adapter
public class DriverAdapter extends ArrayAdapter<Driver> {
public DriverAdapter(Context context, int resource, List<Driver> objects) {
super(context, resource, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
row = convertView;
Holder holder;
if(convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.driver_listview, parent, false);
holder = new Holder();
holder.name = (TextView) row.findViewById(R.id.driverName);
holder.email = (TextView) row.findViewById(R.id.driverMail);
holder.phone = (TextView) row.findViewById(R.id.driverPhone);
row.setTag(holder);
}else {
holder = (Holder) row.getTag();
}
Driver driver = getItem(position);
holder.name.setText(driver.getName());
holder.email.setText(driver.getEmail());
holder.phone.setText(driver.getPhone());
return row;
}
public class Holder {
protected TextView name;
protected TextView email;
protected TextView phone;
}
}
Adapter XML:
<?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"
android:orientation="horizontal">
<TextView
android:id="#+id/driverName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="DriverName"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/black" />
<TextView
android:id="#+id/driverMail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="10dp"
android:text="DriverMail"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/black" />
<TextView
android:id="#+id/driverPhone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="DriverPhone"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/black" />
</LinearLayout>
If this doesn't help you, there is a problem with your fragment showing on the device. As I have tested this myself and it displays correctly on the screen.
Looks like you are setting your adapter to the ListView before you add anything to it, which is fine but you must call adapter.notifyDataSetChanged() in order to update the list with the new data.
Although, I would suggest changing how you create your adapter. Everytime I have used any sort of adapter, I create my list of data before and pass it in through the constructor. Then set it to my listview. So like:
View view;
view = inflater.inflate(R.layout.fragment_driver, container, false);
listView = (ListView) view.findViewById(R.id.driverList);
Driver a = new Driver("John Smith","Johnsmith#example.com","123");
ArrayList<Driver> drivers = new ArrayList();
drivers.add(a);
DriverAdapter driverAdapter = new DriverAdapter(getActivity().getApplicationContext(),R.layout.driver_listview, drivers);
listView.setAdapter(driverAdapter);
This is a only rough example of what I would do, I would advise you to read up on some examples from Google around this. Also read up on RecyclerViews instead of ListViews if possible.
https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html
https://www.bignerdranch.com/blog/recyclerview-part-1-fundamentals-for-listview-experts/
I wanted to do a generic ListAdapter, where instead of inserting predefined view structures, you can add different views in each list item.
I have my ListAdapter:
public class ListAdapter extends BaseAdapter {
private HashMap<Integer, Integer> listDataTypes; //For each element of the list, defines if its an ítem or a separator
private List<View> listData;
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
public ListAdapter() {
listDataTypes = new HashMap<Integer, Integer>();
listData = new ArrayList<>();
}
public void addItem(final View item) {
listDataTypes.put(listData.size(), TYPE_ITEM);
listData.add(item);
notifyDataSetChanged();
}
public void addSeparator(final View item) {
listDataTypes.put(listData.size(), TYPE_SEPARATOR);
listData.add(item);
notifyDataSetChanged();
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getCount() {
return listData.size();
}
#Override
public int getItemViewType(int position) {
return listDataTypes.get(position);
}
#Override
public View getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
View itemView = listData.get(position);
convertView = itemView;
}
return convertView;
}
}
Here is an example of a list_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/tvInfo1"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvInfo2"
android:layout_toLeftOf="#+id/tvInfo3"
android:layout_toStartOf="#+id/tvInfo3"
android:layout_toEndOf="#id/tvInfo1"
android:layout_toRightOf="#id/tvInfo1"
android:layout_centerVertical="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:id="#+id/tvInfo3"
android:layout_centerVertical="true"/>
</RelativeLayout>
</LinearLayout>
And how I use the list adapter:
protected void onCreate(Bundle savedInstanceState) {
...
ListAdapter listAdapter = new ListAdapter();
TextView tvHeader = new TextView(this);
tvHeader.setText("I am a header");
listAdapter.addSeparator(tvHeader);
for(int i=0; i<50; i++){
View itemView = layoutInflater.inflate(R.layout.layout_two_items_list_item, null);
TextView tvInfo1= (TextView) itemView .findViewById(R.id.tvInfo1);
TextView tvInfo2= (TextView) itemView .findViewById(R.id.tvInfo2);
TextView tvInfo3= (TextView) itemView .findViewById(R.id.tvInfo3);
tvInfo1.setText("Id " + i);
tvInfo2.setText("Info " + i);
tvInfo3.setText("Hour " + i);
listAdapter.addItem(itemView);
}
ListView listView = (ListView)findViewById(R.id.listview);
listView.setAdapter(listAdapter);
listView.setSelector(android.R.color.transparent);
}
But for some reason, when I scroll the list, some items start to float, other are not shown, other are repeated, other changes places, etc. What am I doing wrong?
This is how is shown (incorrectly)
It is a very bad practice what you are doing. Keeping an array of views in the memory. The whole purpose of a listview to minimise that. In order to avoid the repetition replace
if (convertView == null) {
View itemView = listData.get(position);
convertView = itemView;
}
return convertView;
with
return listData.get(position);
But if I were you I would seriously consider rewriting the way you are doing your listview.
Change your getView to something like:
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = listData.get(position);
return itemView;
}
I suspect that you're re-using old views when you don't really want to be.
In my app I have a GridView inside ViewPager.
I am not using anywhere match_parent or wrap_content. I am using values like 200dp or 150dp. So why is my getView() of GridView adapter is calling multiple times?
I searched a lot like here,
here, here, and here.
This is my adapter class.
public class CustomGridViewAdapter1 extends BaseAdapter {
ArrayList<Integer> list2 = new ArrayList<Integer>();
private LayoutInflater mInflater;
public CustomGridViewAdapter1(Context context, ArrayList<Integer> list2) {
mInflater = LayoutInflater
.from(context.getApplicationContext());
this.list2 = list2;
}
#Override
public int getCount() {
return 6;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
try {
View hView = convertView;
if (convertView == null) {
hView = mInflater.inflate(R.layout.greeditem, null);
ViewHolder1 holder = new ViewHolder1();
holder.song_pic = (ImageView) hView.findViewById(R.id.pic1);
holder.name = (TextView) hView
.findViewById(R.id.tabletext1);
holder.layout = (LinearLayout) hView
.findViewById(R.id.bingo_rlayout1);
hView.setTag(holder);
}
ViewHolder1 holder = (ViewHolder1) hView.getTag();
imageLoader.DisplayImage(list1.get(position), holder.song_pic);
holder.name.setText(list.get(position));
if (list2.get(position) == 1) {
holder.layout.setBackgroundColor(getActivity()
.getResources().getColor(R.color.lightblue));
holder.name.setTextColor(getActivity().getResources().getColor(R.color.white));
}
return hView;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
And this is my XML layout:
<?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"
android:orientation="vertical" >
<GridView
android:id="#+id/gridView1"
android:layout_width="320dp"
android:layout_height="250dp"
android:layout_below="#+id/ticketText"
android:numColumns="2"
android:background="#fff"
android:listSelector="#android:color/white">
</GridView>
<TextView
android:id="#+id/scoreId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/ticketText"
android:layout_alignBottom="#+id/ticketText"
android:layout_alignParentRight="true"
android:layout_marginRight="32dp"
android:text="Score 1/6"
android:textColor="#000000"
android:textSize="16sp" />
<TextView
android:id="#+id/ticketText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/tablayout"
android:layout_marginLeft="16dp"
android:text="My Ticket #1"
android:textColor="#000000"
android:textSize="16sp" />
</RelativeLayout>
We need to check the null condition in getView(). Try with below code:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
/*
* The convertView argument is essentially a "ScrapView" as described is Lucas post
* http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
* It will have a non-null value when ListView is asking you recycle the row layout.
* So, when convertView is not null, you should simply update its contents instead of inflating a new row layout.
*/
if(convertView==null){
// inflate the layout
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
viewHolder.textViewItem = (TextView) convertView.findViewById(R.id.textViewItem);
// store the holder with the view.
convertView.setTag(viewHolder);
}else{
// we've just avoided calling findViewById() on resource everytime
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
// object item based on the position
ObjectItem objectItem = data[position];
// assign values if the object is not null
if(objectItem != null) {
// get the TextView from the ViewHolder and then set the text (item name) and tag (item ID) values
viewHolder.textViewItem.setText(objectItem.itemName);
viewHolder.textViewItem.setTag(objectItem.itemId);
}
return convertView;
}
I am new in android app dev and I am trying to create a ListFragment consisting of a TextView and a ListView. I want to try and populate the ListView with data from a custom class and thus created a custom ArrayAdapter. My app runs but doesn't show anything in the list and I can't figure out why not. I have logged the data and it is present in the holder and the text seems to be set but something is wrong.
row_layout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip" >
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:id="#+id/TextViewStation"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="My Application" />
<TextView
android:id="#+id/TextViewType"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
android:text="Simple application that shows how to use RelativeLayout" />
</LinearLayout>
</RelativeLayout>
list_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/android:empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="No items to display." />
<ListView
android:id="#+id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
SimpleArrayAdapter.java
public class SimpleArrayAdapter extends ArrayAdapter<Warning> {
private final Context context;
private final List<Warning> objects;
public SimpleArrayAdapter(Context context, int resource,
List<Warning> objects) {
super(context, resource);
this.context = context;
this.objects = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder = new ViewHolder();
if (row == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.row_layout, parent, false);
holder.v1 = (TextView) row.findViewById(R.id.TextViewStation);
holder.v2 = (TextView) row.findViewById(R.id.TextViewType);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
final Warning warning = objects.get(position);
if (warning != null) {
holder.v1.setText(warning.getStation());
holder.v2.setText(warning.getType());
// Log.d("Adapter", "holder.v1.getText(): " + holder.v1.getText());
}
return row;
}
public static class ViewHolder {
TextView v1; // view1
TextView v2; // view2
}
#Override
public int getCount() {
return objects.size();
}
#Override
public Warning getItem(int position) {
// TODO Auto-generated method stub
return objects.get(position);
}
}
List_View.java - the ListFragment
public class List_View extends ListFragment {
List<Warning> items = new ArrayList<Warning>();
Gson gson = new Gson();
private SimpleArrayAdapter adapter;
private ListView mListView;
// #Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ---- Get data!
JsonElement je = new JsonParser().parse(result);
JsonObject jo = je.getAsJsonObject();
JsonArray ja = jo.getAsJsonArray("warnings");
for (int i = 0; i < ja.size(); i++) {
Warning war = new Warning();
war = gson.fromJson(ja.get(i).getAsJsonObject(), Warning.class);
items.add(war);
}
// ----
}
// #Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater
.inflate(R.layout.list_layout, container, false);
// RESTManager manager = new RESTManager();
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d("Adapter", "items.size(): "+ items.size());
adapter = new SimpleArrayAdapter(getActivity(), R.layout.row_layout,
items);
setListAdapter(adapter);
}
}
In SimpleArrayAdapter, me logging the result from holder.v1.getText() returns correct value but still nothing is showing in the ListView in the app.
Try this :
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
TextView station, type ;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.row_layout, parent, false);
station = (TextView) row.findViewById(R.id.TextViewStation);
type = (TextView) row.findViewById(R.id.TextViewType);
}
Warning warning = objects.get(position);
if (warning != null) {
station.setText(warning.getStation());
type.setText(warning.getType());
// Log.d("Adapter", "holder.v1.getText(): " + holder.v1.getText());
}
return row;
}
I found the problem. Stupidly for some reason I had android:layout_width="0dip" for the textviews........ changed to android:layout_width="fill_parent" and boom, there is my data!