I'm trying to build a ListView with a custom layout but so far have not been able to successfully do it. I'm a beginner and have been following tutorials to get it done.
This is what I'm doing:
//this is where I want the custom list items to be displayed.
//GroupAdapter is the constructor of the class in which I'm trying to make a custom adapter
stringArray = new String[10];
groupItemArrayAdapter = new GroupAdapter(this,stringArray);
groupListView = (ListView) findViewById(R.id.mainList);
groupListView.setAdapter(groupItemArrayAdapter);
//this is the code in GroupAdapter.java class
public class GroupAdapter extends ArrayAdapter{
private LayoutInflater inflater;
public GroupAdapter(Activity activity, String[] items){
super(activity,R.layout.group_view);
inflater=activity.getWindow().getLayoutInflater();
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
return inflater.inflate(R.layout.group_view,parent,false);
}
}
When i start the app, a blank screen appears. Initially when i used Android default layout for the list, list items were displayed but not anymore... I don't understand what I'm doing wrong. Can anyone help?
Here is the group_view.xml file
<?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"
android:padding="30dp" >
<TextView
android:id="#+id/gName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Group Name"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_marginRight="100dp"
android:textStyle="bold" />
<TextView
android:id="#+id/activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/signIn"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="5"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold" />
</LinearLayout>
You can replace all your code by next
stringArray = new String[10];
groupItemArrayAdapter = new GroupAdapter(this,stringArray);
groupListView = (ListView) findViewById(R.id.mainList);
groupListView.setAdapter(new ArrayAdapter<String>(this, R.layout.group_view, R.id.gName, stringArray));
it's for case when you want to show strings at gName field, if you want to shot them at activity, then you need to use
groupListView.setAdapter(new ArrayAdapter<String>(this, R.layout.group_view, R.id.activity, stringArray));
Answer for "Why it's blank?"
#Override
public View getView(int position, View convertView, ViewGroup parent){
return inflater.inflate(R.layout.group_view,parent,false);
}
You only inflate empty view and does not assign strings to fields. It would be (simplest version)
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.group_view, parent, false);
TextView textView = (TextView)convertView.findViewById(R.id.gName);
String item = getItem(position)
textView.setText(item);
return convertView;
}
You'll be able to implement better version after read article Making ListView Scrolling Smooth
Related
Right now I have a ListView, with a custom ArrayAdapter to populate the items. Right now the items each only show a little bit of information, I want to be able to tap on an item, and have it 'expand', showing the rest of the information. I would like there to be an animation when it expands. I also want to get there to only be one item 'expanded' at once (ie if one is open, and I tap on another, the first one goes back to normal). I would also like to have expanded items stay expanded, even if they are scrolled out of the view.
This is the code I have now
single_row.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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="FIRST INFO"
android:id="#+id/first"/>
<Space
android:layout_width="match_parent"
android:layout_height="15dp"
android:id="#+id/space"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SECOND INFO"
android:id="#+id/hidden"/>
</RelativeLayout>
my_cards.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="#191919"
android:id="#+id/card_layout"
android:weightSum="1">
<Space
android:layout_width="match_parent"
android:layout_height="29dp"
android:layout_gravity="center_horizontal"/>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"
android:id="#+id/list_view"
android:divider="#191919"
android:layout_marginRight="23dp"
android:layout_marginLeft="23dp"
android:dividerHeight="12dp"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
MyCards.java
public class MyCards extends android.support.v4.app.Fragment{
private ListView mListView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Inflate the view
View view = inflater.inflate(R.layout.my_cards, container, false);
//Arrays for test information
String[] names = {"Tim", "Kevin", "Bob", "John","Evan", "Roy", "Tristan", "Ronald"};
String[] company = {"Apple", "Microsoft", "China", "Xiaomi","Facebook", "Unemployed", "CCP", "Government"};
//Get reference to the listview
mListView = (ListView) view.findViewById( R.id.list_view );
//Initialize the adapter, and set it to the listview
customAdapter adapter = new customAdapter(getContext(),names,company);
mListView.setAdapter(adapter);
return view;
}
}
class customAdapter extends ArrayAdapter<String>{
Context mContext;
String[] mName;
String[] mCompany;
customAdapter(Context c, String[] names, String[] companies){
super(c, R.layout.single_row, R.id.name, names);
this.mContext = c;
this.mName = names;
this.mCompany = companies;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View mRow = inflater.inflate(R.layout.single_row, parent, false);
TextView mNameText = (TextView) mRow.findViewById(R.id.name);
TextView mCompanyText = (TextView) mRow.findViewById(R.id.company);
mNameText.setText(mName[position]);
mCompanyText.setText(mCompany[position]);
mRow.setBackgroundResource(R.drawable.custom_listview_shape);
return mRow;
}
}
Now, I have tried to have a go at getting this to work. I tried adding this to my onCreateView method
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView hidden = (TextView) view.findViewById(R.id.hidden);
if ( hidden.getVisibility() == View.GONE)
{
//expandedChildList.set(arg2, true);
hidden.setVisibility(View.VISIBLE);
}
else
{
//expandedChildList.set(arg2, false);
hidden.setVisibility(View.GONE);
}
}
});
Now, while this technically does what I want it to do (cause item to expand on click), it doesn't do it the way I would like to. There is no animation, multiple items can be expanded at once, and it goes back to normal as soon as it is scrolled out of view.
Any help with this would be greatly appreciated.
I have a spinner in a Layout, it is defined as
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/bithYearSpinner"
android:layout_marginTop="15dp" />
Spinner declaration and Adapter:
birthYearSpinner = (Spinner) findViewById(R.id.bithYearSpinner);
String[] years = getResources().getStringArray(R.array.bithYears);
ArrayAdapter<String> adapter = new ArrayAdapter<String(this,android.R.layout.simple_spinner_dropdown_item,years);
birthYearSpinner.setAdapter(adapter);
The problem is, spinner shows up with white text on white background which is impossible to see its items. I have done a research about it, some people have the same problem and there are some solutions but they dont work out for me. How can i fix this ? Any help would be appreciated.
To fix it, you can use custom xml layout for spinner item. By doing this, you can customize your spinner item text color and background.
Create item_spinner.xml and then,
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="19sp"
android:textColor="#111111"
android:padding="8dp"
/>
And set your custom layout to adapter like this :
birthYearSpinner = (Spinner) findViewById(R.id.bithYearSpinner);
String[] years = getResources().getStringArray(R.array.bithYears);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.item_spinner, years);
birthYearSpinner.setAdapter(adapter);
Edit
If it is in fragment, try to replace this with getActivity() . Please look at this answer for reference.
create custom rowlayout for spinner and name it as spinner_item.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:background="#color/theme_color"
android:orientation="vertical">
<TextView
android:id="#+id/spinnerText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#ff00ff"
android:gravity="center"
android:paddingBottom="5dip"
android:paddingTop="5dip"
android:text=""
android:textColor="#000000"
android:textSize="18sp" />
</LinearLayout>
now create Adapter and name it as DropDownAdapter.java
package com.ronem.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.ronem.goldsilverpricenepal.R;
public class DropDownAdapter extends ArrayAdapter<String> {
LayoutInflater inflater;
String[] genereValue;
public DropDownAdapter(Context context, int textViewResourceId,
String[] genereValue) {
super(context, textViewResourceId, genereValue);
inflater = LayoutInflater.from(context);
this.genereValue = genereValue;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView, ViewGroup parent) {
// LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.spinner_item_layou, parent, false);
TextView label = (TextView) convertView.findViewById(R.id.spinnerText);
label.setText(genereValue[position]);
return convertView;
}
}
now initialize and set custom adapter as shown in your activity
DropDownAdapter dAdapter = new DropDownAdapter(this, R.layout.spinner_item_layou, spinnerValues);
itemSpinner.setAdapter(dAdapter);
When i change my resource array <array name=""> to <string-array name="">, spinner items show up properly and no need to use a custom adapter.
I am new to android and am trying to create two fragments and have it so you can slide between the two, one is a list and the otehr a grid. I had the list working when it when I was using an ArrayAdapter and had my EventListFragment extending ListFragment (if code is helpful let me know and ill post that part)
I am now trying to create a custom list view with multiline list items (let me know if there is an easier way and if i have simply overcomplicated the whole thing)
Here is my code:
Event List Fragment:
public class EventListFragment extends Fragment {
ArrayList<EventObject> eventObjects;
#Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
eventObjects = ((EventsActivity)getActivity()).getEventObjects();
View view = inflater.inflate(R.layout.eventgrid ,container,false);
Listview listView = (ListView) view.findViewById(R.id.listView);
if (listView == null) {
System.out.println("asas");
}
listView.setAdapter(new MyCustomBaseAdapter(getActivity().getBaseContext(), eventObjects));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Object o = listView.getItemAtPosition(position);
EventObject fullObject = (EventObject)o;
System.out.println("asd");
}
});
return view;
}
}
The corresponding xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<ListView
android:id="#+id/listView"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</RelativeLayout>
The xml for the customgridrow:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="#+id/name"
android:textSize="14sp"
android:textStyle="bold"
android:textColor="#FFFF00"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/cityState"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
EDIT
The getView() from MyCustomBaseAdapter :
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.customgridrow, null);
holder = new ViewHolder();
holder.txtName = (TextView) convertView.findViewById(R.id.name);
holder.txtCityState = (TextView) convertView.findViewById(R.id.cityState);
holder.txtPhone = (TextView) convertView.findViewById(R.id.phone);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.txtName.setText(events.get(position).getName());
holder.txtCityState.setText(events.get(position).getDate());
holder.txtPhone.setText(events.get(position).getVenue());
return convertView;
}
From your comments
You are inflating the wrong layout
You should inflate the one that has listview and initialize the same.
Change
View view = inflater.inflate(R.layout.eventgrid ,container,false);
to
View view = inflater.inflate(R.layout.eventList ,container,false);
Every time you want to add an object to a list, you have to provide a view for the object. Android asks your list adapter, be it custom or system-defined, it asks the adapter what each list item is supposed to look like. This is where getView() comes into play.
public abstract View getView (int position, View convertView, ViewGroup parent):
Get a View that displays the data at the specified position in the data set.
If convertView is null, you will get an NPE.
Tutorials here: http://www.javacodegeeks.com/2013/06/android-listview-tutorial-and-basic-example.html
I connent an addevent.java with addevent.xml is content a listview, the listview take its element from another XML file "item.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" >
<Button
android:id="#+id/d"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:drawablePadding="0dip"
android:drawableRight="#drawable/icon_name" />
<EditText
android:id="#+id/en"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/d" >
</EditText>
</LinearLayout>
now I need to findviewbyId not from basic xml file but form another "item.xml"
I tried LayoutInflater as this, code but it isn't work:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.addevent);
myList = (ListView) findViewById(R.id.MyList);
myList.setItemsCanFocus(true);
myAdapter = new MyAdapter();
myList.setAdapter(myAdapter);
final LayoutInflater factory = getLayoutInflater();
final View textEntryView = factory.inflate(R.layout.item, null);
tvDisplayDate = (EditText)textEntryView.findViewById(R.id.editd);
btnChangeDate=(Button)textEntryView.findViewById(R.id.d);
any help please
Try this View view = LayoutInflater.from(getApplication()).inflate(R.layout.item, null);
How you can see, static from() method takes 1 argument(Context) and you obtains LayoutInflater from given Context, in your case it will be your Activity where you want to inflate View.
Hope it helps!
From insinde your MyAdapter class you can override the getView method (that's the one that produces the item renderers on demand).
After recycling / inflating the proper layout for the current item (say convertView), you can access all of its children using the findViewById method called on the convertView:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
// initialize, inflate convertView from your layout if needed;
tvDisplayDate = (EditText)convertView.findViewById(R.id.editd);
// populate convertView with the item's details
}
I am developing an android application which contains a ListAtivity class and get it is data as follow :
ArrayAdapter<Item> ara=new MyArrayAdapter(this,_items);
setListAdapter(ara);
And I defined MyArrayAdapter :
....
public MyArrayAdapter(Activity context, List<BirthdayContact> list) {
super(context,R.layout.list_row,0,list);
//super(context, R.layout.birthday_list, list);
this.context = context;
this.list = list;
}
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.birthday_list_row, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder._cName= (TextView) view.findViewById(R.id.contact_name);
viewHolder._cImage = (ImageView) view.findViewById(R.id.contact_image);
viewHolder._cbirthDay=(TextView)view.findViewById(R.id.contact_birthday_remained);
view.setTag(viewHolder);
}
......
But the problem with this way is that you cant only assign each row`s template and you cant have other widget on list view which are not part of list of data. I mean I want to have a say a TextView which shows messages to user, and below that I show the list of rows.
Can you help me please?
If you want a different layout than a simple ListView you have the option of setting the content view to a layout file like this:
setContentView(R.layout.layout_with_diferrent_views); // call this on the onCreate() method
where R.layout.layout_with_different_views could be a xml layout like this:
<?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/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Because you extends ListActivity you must have in the layout a ListView element with the id #android:id/list. Of course you can have a more complex layout than the one above as long as you have a ListView element with the id #android:id/list
You should consider using a listHeader : lv.addHeaderView(findViewById(R.id.header));
This has to be done in your onCreate method in your activity, and you must provide a widget with the id header.
If you want other components in activity.Then better consider Normal Activity instead ListActivity.