I'm trying to create some layouts dynamically and then inflate them.
Currently I have some layouts and I'm inflating them by using my own adapter class.
However now I need to create some cards based on data that is generated. I tried using the card class for this like this for example
for (int i = 1; i < 10; i++) {
Card card = new Card(this);
card.setText("Test " + i);
mCards.add(card);
}
I can't get this designed how I would want it tho. So is there a way for me to use the xml setup to do this since I have more design options this way?
at the risk of getting downvoted again I'll post my solution
for now this is just a test to see if it would function the way I want to.
Later on I will have the cards generated from an actual list with data inside of it.
First I created a xml layout with a textview inside it
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:id="#+id/test_content"
android:textSize="47pt"/>
</LinearLayout>
after that I created a adapter that will inflate the layout and set the textview for each item in the list
public class xmlAdapter extends CardScrollAdapter {
private List<Integer> mCards;
private LayoutInflater mInflater;
public xmlAdapter(List<Integer> mCards, LayoutInflater inflater)
{
this.mCards = mCards;
this.mInflater = inflater;
}
#Override
public int getCount() {
return mCards.size();
}
#Override
public Object getItem(int i) {
return mCards.get(i);
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
View mView = view;
view = mInflater.inflate(R.layout.xml_test, viewGroup, false);
TextView text = (TextView) view.findViewById(R.id.test_content);
text.setText("Test " + mCards.get(i));
view.setTag(text);
return view;
}
#Override
public int getPosition(Object o) {
return this.mCards.indexOf(o);
}
}
and in my activity class I've done the following.
in the onCreate()
CreateCards();
mCardScroller = new CardScrollView(this);
mCardScroller.setAdapter(new xmlAdapter(numberCards, getLayoutInflater()));
mCardScroller.setOnItemClickListener(this);
take in mind that this is just a for loop to put some data in the list that is being send to the adapter.
public void CreateCards() {
for (int i = 1; i < 10; i++) {
numberCards.add(i);
}
}
Related
Actually i'm trying to make an app that take restaurant orders and i'm having some issues after adding child item to my order.
I have a recyclerView where i have different type's of food when i press on one of them i add it to recyclerView that work's something like a notebook, then i have an button that open an AlertDialog in which there is another recyclerView with variant's.
Example: i press on PIZZA from food recyclerView it's add it to the notebook after i press on variant's and i can add "WITH PEPERONI" or "LARGE" or both.
I have followed this guide ( here github project from the guide) for making the recyclerView with child item.
Now the issue is how can i add the child item to the last parent item?
like i'm adding parent item using this:
dummyParentDataItem = new ItemPTERM();
dummyParentDataItem.setButton_name(filteredList.get(position).getDeskS());
dummyParentDataItem.setQuant( Integer.parseInt(filteredList.get(position).getQuant()));
dummyChildDataItems = new ArrayList<>();
dummyParentDataItem.setChildDataItems(dummyChildDataItems);
itemCassas.add(dummyParentDataItem);
And this when i add a child from variant's recyclerView
dummyChildDataItem = new DummyChildDataItem();
dummyChildDataItem.setChildName(tipo.toString());
dummyChildDataItems.add(dummyChildDataItem);
dummyParentDataItem.setChildDataItems(dummyChildDataItems);
itemCassas.add(dummyParentDataItem);
but obviously the app crash because that don't know which is the last paren't item to which add the child.
When i try to put both parent and child when i'm adding food from recyclerView with:
dummyParentDataItem = new ItemPTERM();
dummyParentDataItem.setButton_name(filteredList.get(position).getDeskS());
dummyParentDataItem.setQuant( Integer.parseInt(filteredList.get(position).getQuant()));
dummyChildDataItems = new ArrayList<>();
dummyChildDataItem = new DummyChildDataItem();
dummyChildDataItem.setChildName("WITH PEPERONI");
dummyChildDataItems.add(dummyChildDataItem);
dummyParentDataItem.setChildDataItems(dummyChildDataItems);
itemCassas.add(dummyParentDataItem);
that obviously works but i have to add the child in a separate method to the last parent.
How can i do it? any suggestion?
Here is also my adapter code:
public class AdapterPTERM extends RecyclerView.Adapter<AdapterPTERM.ExampleViewHolder> {
private ArrayList<ItemPTERM> mExampleList;
#NonNull
#Override
public ExampleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_pterm,parent,false);
return new ExampleViewHolder(v);
}
AdapterPTERM(ArrayList<ItemPTERM> exampleList){
mExampleList = exampleList;
}
#Override
public void onBindViewHolder(#NonNull ExampleViewHolder holder, int position) {
ItemPTERM item = mExampleList.get(position);
holder.desc.setText(item.getBtnName());
holder.qta.setText(String.valueOf(item.getQuant()));
int noOfChildTextViews = holder.linearLayout_childItems.getChildCount();
int noOfChild = item.getChildDataItems().size();
if (noOfChild < noOfChildTextViews) {
for (int index = noOfChild; index < noOfChildTextViews; index++) {
TextView currentTextView = (TextView) holder.linearLayout_childItems.getChildAt(index);
currentTextView.setVisibility(View.GONE);
}
}
for (int textViewIndex = 0; textViewIndex < noOfChild; textViewIndex++) {
TextView currentTextView = (TextView) holder.linearLayout_childItems.getChildAt(textViewIndex);
currentTextView.setText(item.getChildDataItems().get(textViewIndex).getChildName());
}
if(position % 2 == 0 ){
holder.itemView.setBackgroundColor(Color.parseColor("#C0C0C0"));
}else if(position % 2 == 1){
holder.itemView.setBackgroundColor(Color.parseColor("#D3D3D3"));
}
}
#Override
public int getItemCount() {
return mExampleList.size();
}
public class ExampleViewHolder extends RecyclerView.ViewHolder {
public TextView desc;
public TextView qta;
private LinearLayout linearLayout_childItems;
private Context context;
ExampleViewHolder(View itemView) {
super(itemView);
desc = itemView.findViewById(R.id.Desc);
qta = itemView.findViewById(R.id.Qta);
linearLayout_childItems = itemView.findViewById(R.id.ll_child_items);
context = itemView.getContext();
int intMaxNoOfChild = 0;
for (int index = 0; index < mExampleList.size(); index++) {
int intMaxSizeTemp = mExampleList.get(index).getChildDataItems().size();
if (intMaxSizeTemp > intMaxNoOfChild) intMaxNoOfChild = intMaxSizeTemp;
}
for (int indexView = 0; indexView < intMaxNoOfChild; indexView++) {
TextView textView = new TextView(context);
textView.setId(indexView);
textView.setPadding(0, 20, 0, 20);
textView.setGravity(Gravity.CENTER);
textView.setBackground(ContextCompat.getDrawable(context, R.drawable.background_sub_module_text));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
linearLayout_childItems.addView(textView, layoutParams);
}
}
}
public void removeItem(int position) {
mExampleList.remove(position);
notifyItemRemoved(position);
}
}
Here is a screenshot of my activity
To display data in a RecylerView, you provide a list of items to its adapter.
To add a new element you just need to add the item to the list and call notifyDataSetChange() on the adapter.
For example you can create a new method in you adapter, like that:
public void addItem(ItemPTERM item){
mExampleList.add(item);
notifyDataSetChange();
}
EDIT
So what you can do is to allow your item to have a list of 'variants'.
For example if you select 'Pizza' and want to had 'big' and 'pepperoni', your item will be the pizza and 'big'and 'pepperoni' part of the variants list.
Food {
String name;
List<Variant> variants;
//... Other attributes
public void setVariant(Variant variant){
if (variants == null) // We want to initialise the array only when necessary
variants = new ArrayList<>();
variants.add(variant);
}
#Nullable
public List<Variant> getVariants(){
return variants;
}
}
Variant{
String name;
//... Other attributes
}
When you select a variant you add it to the appropriate Food object.
Approach 1
Then in your adapter, in the onBindViewHolder you can dynamically add the variants to the item;
This way is not the most optimised but should work:
Item layout
<!-- Food Views-->
...
<!-- Container for the variants -->
<LinearLayout
android:id="#+id/variants_list"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content"/>
</LinearLayout>
Variant 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"
android:orientation="horizontal">
<TextView
android:id="#+id/variant_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/variant_other_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Adapter
final LayoutInflater mInflater;
List<Food> mFoods;
public FoodAdapter(Context context, ...){
//...
mInflater = LayoutInflater.from(context);
}
#Override
public void onBindViewHolder(#NonNull ExampleViewHolder holder, int position) {
Food food = mFood.get(position);
// Display food attributes
//...
// Clear the container to set fresh info
holder.variantsContainer.removeAllViews();
List<Variant> variants = food.getVariants();
if (variants != null && variants.size() > 0){
// Display the variants when necessary
for(Variant v : variants){
View vView = mInflater.inflate(R.layout.variant_layout);
TextView nameTV = vView.findViewById(R.id.variant_name);
nameTV.setText(v.getName());
// Set other fields values
// ...
holder.variantsContainer.addView(vView);
}
}
}
Approach 2
Another way to do it is to have a list of food object containing a list of variant as above, but to not use this list directly in the adapter.
Instead the adapter will use it's own list which will be both Food and Variant objects mix together. Your adapter should then be able to display 2 kinds of objects. This way is more flexible but you have to recreate the entire adapter list every time you change something.
For instance:
Let say you have 3 Food objects in the list. The first one has 1 variant, the second one none and the third one 2.
Then your adapter will get a list like that:
List<Object> items;
items will contain:
{food1, variant1a, food2, food3, variant3a, variant3b}
And then your adapter will have to use two different layout to display either the Food or the Variant object.
#NonNull
#Override
public ExampleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == 0) { // if food
View vFood = mInflater.inflate(R.layout.food_layout, parent, false);
return new FoodViewHolder(vFood);
} else { // variant
View vVariant = mInflater.inflate(R.layout.variant_layout, parent, false);
return new VariantViewHolder(vVariant;
}
}
#Override
public int getItemViewType(int position) {
return (mItems.get(position) instanceof Food) ? 0 : 1;
}
I want to implement swapping ListView item with animations like in XE Currency Application
from the list when user tap on GBP-British Pound that row will go up side and fit upon INR - Indian Rupee with animations and row INR - Indian Rupee will replace on place of GBP-British Pound
I have tried one animation in listview (used header in listview) then it is working perfect, but the issue is that the header is also scrolled up and down with listview and I want the header view (or any view) fixed at top and below it list can be scrolled
I have tried one fix view at top in Relative Layout and keep listview below the top view at that time animation is worked but inside only listview not outside of listview
how can we implement that in android ?
Why reinvent the wheel? There's out a couple of well-documented and well-structured libraries for dealing with ListView. For example ListViewAnimations is the best one, IMO.
Features
Appearance animations for items in ListViews, GridViews, other AbsListViews
Built in animations include Alpha, SwingRightIn, SwingLeftIn, SwingBottomIn, SwingRightIn and ScaleIn.
Other animations can easily be added
StickyListHeaders is supported, other implementations can easily be added.
Swipe-to-Dismiss, Swipe-To-Dismiss with contextual undo
Drag-and-Drop reordering This is what you need
Animate addition of items
Smoothly expand your items to reveal more content
I had pretty similar problem a while ago. I needed to have a page, where I can re-arrange entries (musical song tracks). So here's my implementation:
DynamicListView (too long to post it here)
My AllTracksFragment, that allows to re-order tracks
public class AllTracksFragment extends SupportFragmentBase {
DynamicListView allTracksListView;
private ArrayList<Track> allTracksList = new ArrayList<>();
TracksListViewAdapter allTracksAdapter;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_all_tracks, container, false);
setHasOptionsMenu(true);
allTracksListView = (DynamicListView)rootView .findViewById(R.id.allTracksListView);
Track track1 = new Track(); // Track is simple model class
track1.trackName = "Winter\'s Coming (Acoustic) 1";
track1.trackId = "47580057";
Track track2 = new Track();
track2.trackName = "Winter\'s Coming (Acoustic) 2";
track2.trackId = "47580057";
Track track3 = new Track();
track3.trackName = "Winter\'s Coming (Acoustic) 3";
track3.trackId = "47580057";
allTracksList.add(track1);
allTracksList.add(track2);
allTracksList.add(track3);
allTracksAdapter = new TracksListViewAdapter(allTracksList, eventBus);
allTracksListView.setTracksList(allTracksList); //SEE DynamicListView class
allTracksListView.setAdapter(allTracksAdapter);
allTracksListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
return rootView;
}
}
And the AllTracksFragment layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.myapp.views.DynamicListView
android:id="#+id/allTracksListView"
android:layout_marginTop="12dp"
android:scrollbars="none"
android:divider="#null"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
TracksListViewAdapter (if needed):
public final class TracksListViewAdapter extends BaseListViewArrayAdapter<PlayTrackView, Track> { // extended version of simple BaseAdapter
final int INVALID_ID = -1;
public TracksListViewAdapter(final List<Track> tracks) {
super(tracks == null ? new ArrayList<Track>(0) : tracks);
if (tracks != null) {
for (int i = 0; i < tracks.size(); ++i) {
mIdMap.put(tracks.get(i), i);
}
}
}
public PlayTrackView createNewView(final Context context, final int position) {
return new PlayTrackView(context); // PlayTrackView - is an extension of FrameLayout
}
HashMap<Track, Integer> mIdMap = new HashMap<>();
#Override
public long getItemId(int position) {
if (position < 0 || position >= mIdMap.size()) {
return INVALID_ID;
}
Track item = (Track) getItem(position);
return mIdMap.get(item);
}
#Override
public boolean hasStableIds()
{
return android.os.Build.VERSION.SDK_INT < 20;
}
}
PlayTrackView.java
public class PlayTrackView extends FrameLayout implements IItemDisplayer<Track> {
public PlayTrackView(Context context) {
super(context);
LayoutInflater.from(context).inflate(R.layout.play_track_view, this);
}
public PlayTrackView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.play_track_view, this);
}
public PlayTrackView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater.from(context).inflate(R.layout.play_track_view, this);
}
#Override
public void displayItem(Track track) {
}
}
Track.java
public class Track {
public String trackId;
public String trackName;
}
IItemDisplayer interface
public interface IItemDisplayer<TItem> {
public void displayItem(TItem item);
}
BaseListViewAdapter
BaseListViewArrayAdapter
I am implmenting a Fragment activity that implements ActionBar.TabListener, so I have 3 tabs that each have ListFragments which have a list populated with data obtained through the server. I have been facing this issue for a while now, and I couldn't find an answer no matter how many questions I looked into regarding this particular issue or how many tutorials I looked at in regarding implementing ListFragments with custom array adapters.
The issue I'm having is that I couldn't get the data on the Listview to display on the app. I have managed to obtain the data through the server that I needed to populate the Custom Array Adapter before setting the adapter to the ListView. I even debugged the code and it says that the data is populated in the Adapter as well as in the Listview after making the call to set the array adapter to that Listview. Yet, I couldn't get the data in the Listview to show up in the app. I have been looking into this issue for a while now and I looked into this issue through tutorials and questions posted in forums for any suggestions(Even this one) and I have yet to find anything that has helped me resolve my issue. If anyone could point out on what I did wrong and offer suggestions to fix this issue, I'd gladly appreciate any input.
Code for the ListFragment Activity
public class MyJobsActivity extends ListFragment{
private ArrayList<Job> myJobs;
private static ListView listView;
private static ArrayList<Job> jobList;
ActionBar titleBar;
MyJobsActivity disAllList;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myJobs = (ArrayList<Job>) getArguments().getSerializable(Constants.MYJOBS);
jobList = new ArrayList<Job>();
Job datJob;
for(int i = 0; i < myJobs.size(); i++){
datJob = new Job();
datJob.setJobId(myJobs.get(i).getJobId());
datJob.setJobTitle(myJobs.get(i).getJobTitle());
datJob.setCompany(myJobs.get(i).getCompany());
datJob.setLocation(myJobs.get(i).getLocation());
jobList.add(datJob);
}
MyJobsAdapter datAdapter = new MyJobsAdapter(getActivity(), R.layout.job_row, jobList);
listView.setAdapter(datAdapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
try{
Intent datIntent = new Intent(getActivity(),JobActivity.class);
Job job = jobList.get(position);
datIntent.putExtra(Constants.JOBID, job.getJobId());
datIntent.putExtra(Constants.JOBTITLE, job.getJobTitle());
startActivity(datIntent);
}
catch(RuntimeException e){
e.printStackTrace();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.activity_my_jobs, container, false);
listView = (ListView) rootView.findViewById(android.R.id.list);
return rootView;
}
}
XML file for ListFragment Activity
<?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:gravity="center_horizontal"
android:orientation="vertical"
android:background="#FFFFFF">
<ListView
android:id="#android:id/list"
android:drawSelectorOnTop="false"
android:tag="my_jobs"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="match_parent" />
</LinearLayout>
Code for the custom array adapter
public class MyJobsAdapter extends ArrayAdapter<Job> {
private Activity activity;
private ArrayList<Job> data;
private HashMap<Integer, Boolean> selection;
private static LayoutInflater inflater=null;
private TextView jobPosition, company, location;
private CheckBox jobChecked;
private View actionView;
private int height, prevSize;
private ActionMode datMode;
public MyJobsAdapter(Activity a, int layoutResourceId, ArrayList<Job> jobs) {
super (a, layoutResourceId, jobs);
this.selection = new HashMap<Integer, Boolean>();
this.activity = a;
this.data = jobs;
}
private class ViewHolder {
TextView jobTitle;
TextView companyName;
TextView location;
}
/*public void setData(ArrayList<Job> d){
data = d;
if(data != null){
for (Job job : d){
add(job);
}
}
this.notifyDataSetChanged();
} */
public void setNewSelection(int position, boolean value){
prevSize = selection.size();
selection.put(position, value);
this.notifyDataSetChanged();
}
public boolean isPositionChecked(int position, boolean value){
boolean result = selection.get(position);
return result == true ? result : false;
}
public void removedSelection(int position){
prevSize = selection.size();
selection.remove(position);
this.notifyDataSetChanged();
}
public void clearSelection(){
prevSize = 0;
selection = new HashMap<Integer, Boolean>();
this.notifyDataSetChanged();
}
#Override
public int getCount() {
return data.size();
}
#Override
public long getItemId(int position) {
return position;
}
public void setMode(ActionMode mode){
datMode = mode;
}
public int getSelectedNumberOfItems(){
return selection.size();
}
public HashMap<Integer, Boolean> getSelectedList(){
return selection;
}
public ArrayList<Job> getData(){
return data;
}
public int getHeight(){
return height;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder jobHolder = null;
Job rowItem = getItem(position);
if(convertView==null){
convertView = inflater.inflate(R.layout.job_row, parent, false);
convertView.setBackgroundResource(R.drawable.list_selector);
jobHolder = new ViewHolder();
jobHolder.jobTitle = (TextView) convertView.findViewById(R.id.Position);
jobHolder.companyName = (TextView) convertView.findViewById(R.id.Company);
jobHolder.location = (TextView) convertView.findViewById(R.id.Location);
convertView.setTag(jobHolder);
} else{
jobHolder = (ViewHolder) convertView.getTag();
}
/* jobPosition = (TextView)vi.findViewById(R.id.Position);
company = (TextView)vi.findViewById(R.id.Company);
location = (TextView)vi.findViewById(R.id.Location);
jobChecked = (CheckBox)vi.findViewById(R.id.JobSelected);
jobChecked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
StringBuilder lSelectedString = new StringBuilder(selection.size()).append(Constants.SELECTED);
if(isChecked){
setNewSelection(position,true);
datMode.setTitle(lSelectedString.toString());
}
else{
removedSelection(position);
datMode.setTitle(lSelectedString.toString());
if(selection.size() < 1)
datMode.finish();
}
}
});
if(selection.size() == 0){
jobChecked.setVisibility(View.GONE);
}
else{
jobChecked.setVisibility(View.VISIBLE);
jobChecked.setChecked(selection.get(position) == null ? false : true);
}
vi.setBackgroundResource(selection.get(position) == null ? color.white_color : color.holo_blue_bright);
*/
jobHolder.jobTitle.setText(rowItem.getJobTitle());
jobHolder.companyName.setText(rowItem.getCompany());
jobHolder.location.setText(rowItem.getLocation());
return convertView;
}
}
Code for each row in the ListView
<?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:background="#color/light_gray"
android:paddingTop="8dip"
android:paddingBottom="8dip"
android:descendantFocusability="blocksDescendants">
<RelativeLayout
android:id="#+id/JobRow"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<CheckBox
android:id="#+id/JobSelected"
android:layout_centerVertical ="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/Position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/dark_gray_position"
android:layout_toRightOf="#+id/JobSelected"
android:typeface="sans"
android:fontFamily="Roboto Regular"
android:textSize="22sp"
android:paddingLeft="4dip"/>
<TextView
android:id="#+id/Company"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#color/blue_company"
android:textSize="18sp"
android:fontFamily="Roboto Regular"
android:paddingLeft="4dip"
android:layout_below="#+id/Position"
android:layout_toRightOf="#+id/JobSelected"/>
<TextView
android:id="#+id/Location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/Company"
android:layout_toRightOf="#+id/JobSelected"
android:paddingBottom="8dip"
android:paddingLeft="4dip"
android:textColor="#color/steel_gray_location"
android:fontFamily="Roboto Regular"
android:textSize="14sp"/>
</RelativeLayout>
</RelativeLayout>
Well there are a few issues you might have with the fragment lifecycle due to the statics in your MyJobsActivity, but as for showing the data itself:
In your MyJobsActivity.onActivityCreated (or wherever you end up associating your custom adapter with the underlying ListFragment), you need to use setListAdapter instead of setAdapter.
From the ListFragment docs (see Binding to Data):
You must use ListFragment.setListAdapter() to associate the list with an adapter. Do not directly call ListView.setAdapter() or else important initialization will be skipped.
To be a bit more clear, one of the many benefits of using/extending a ListFragment is that it will internally handle the binding between your custom adapter and the underlying ListView, but the adapter must be added to the ListFragment itself (i.e., setListAdapter), not on the ListView.
A few other observations:
In fact, unless you need a custom layout, I would recommend completely removing your implementation of onCreateView. This will allow the ListFragment to use its default layout, initialization, and handling for its internal ListView and you'll get (default) handling of an empty list, a loading progress bar, etc. as well.
Given the code you've posted, I would recommend against using a private ListView member in your MyJobsActivity - its parent ListFragment already maintains a copy of the underlying ListView for you, and if you're properly setting the adapter via setListAdapter, you don't need the explicit object (and if you do, use ListFragment's getListView()).
Regardless, if my own trials and challenges are any indication, the static ListView and ArrayList members will most certainly cause you grief when the fragment is destroyed and recreated (on orientation change, on restore of your app from the Recents list if the process has been torn down in the interim, etc.).
I have a WebService which return user details like User Name, its Date of Birth and Address. I am calling this web service to my android application developed Xamarin c#. But don't know how to show data (bind data) in Grid View. can some one provide sample code or explain how to show data in Grid View.
What you need to do, is to create an adapter for the GridView and axml layout (the view of the components in the GridView). For example, suppose that you want to make a GridView of Tiles with blue background and with a text at the left bottom corner with white color:
tile.axml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tile_layout"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="#0000FF">
<TextView
android:id="#+id/tile_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:paddingLeft="6dp"
android:paddingBottom="2dp"
android:textColor="#ffffff" />
</RelativeLayout>
TileAdapter.cs
public class TileAdapter : BaseAdapter<BaseTileItem>
{
protected Activity _context = null;
protected List<BaseTileItem> _tileList = new List<BaseTileItem>();
public TileAdapter(Activity context, List<BaseTileItem> tileList)
: base()
{
this._context = context;
this._tileList = tileList;
}
public override BaseTileItem this[int position]
{
get { return this._tileList[position]; }
}
public override long GetItemId(int position)
{
return position;
}
public override int Count
{
get { return this._tileList.Count; }
}
/// Inflates the Tile layout and sets the values
public override Android.Views.View GetView(int position, Android.Views.View convertView, Android.Views.ViewGroup parent)
{
// Get our object for this position
var item = this._tileList[position];
//Try to reuse convertView if it's not null, otherwise inflate it from our item layout
var view = (convertView ??
this._context.LayoutInflater.Inflate(
Resource.Layout.tile,
parent,
false)) as RelativeLayout;
// Find references to each subview in the list item's view
TextView itemText = view.FindViewById<TextView>(Resource.Id.tile_text);
//Assign this item's values to the various subviews
itemText.Text = this._tileList[position].Text;
//Finally return the view
return view;
}
}
}
TileBaseItem.cs
//This is what you retrieve from the webservice
public class BaseTileItem
{
private string _text;
public BaseTileItem(string text)
{
this._text = text;
}
public string Text {
get {return this._text; }
set { this._text = value; }
}
And then in your activity :
private List<BaseTileItem> _usersList;
private TileAdapter _usersAdapter;
private GridView _usersGridView;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
this.SetContentView(Resource.Layout.startactivity);
//inflate all views
InflateViews();
this._usersList = //populate the list with BaseTileItem items
this._usersAdapter = new TileAdapter(this, this._usersList);
//creating the GridView
this._usersGridView = new GridView(this);
this._usersGridView.SetNumColumns(2);
this._usersGridView.SetGravity(GravityFlags.Center);
this._usersGridView.SetPadding(0, 20, 0, 20);
this._usersGridView.SetVerticalSpacing(20);
this._usersGridView.Adapter = this._usersAdapter;
}
Is there a good tutorial or link that shows how to add different items to a listview?
For example, one with two Text lines and a Check box, another that you just press and and something would pop up. All I have now is every list item is the same two line text view and checkbox...
Or, if there is a way to add 1 row at a time with a different layout through R.layout.xxx?
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mRoot = inflater.inflate(R.layout.frag_settings, container, false);
mItems = getResources().getStringArray(R.array.setting_items);
mItemDescription = getResources().getStringArray(R.array.setting_item_descriptions);
mItemListView = (ListView) mRoot.findViewById(R.id.lvMainListView);
ArrayAdapter<String> lvRowTitle = new ArrayAdapter<String>(getActivity(),
R.layout.setting_twolinetext_checkbox, R.id.tvRowTitle,
mItems);
mItemListView.setAdapter(lvRowTitle);
ArrayAdapter<String> lvRowDesc = new ArrayAdapter<String>(getActivity(),
R.layout.setting_twolinetext_checkbox, R.id.tvRowDesc,
mItemDescription);
mItemListView.setAdapter(lvRowDesc);
return mRoot;
In my example, the list activity that will display our custom list view is called OptionsActivity, because in my project this activity is going to display the different options my user can set to control my app. There are two list item types, one list item type just has a TextView and the second list item type just has a Button. You can put any widgets you like inside each list item type, but I kept this example simple.
The getItemView method checks to see which list items should be type 1 or type 2. According to my static ints I defined up top, the first 5 list items will be list item type 1, and the last 5 list items will be list item type 2. So if you compile and run this, you will have a ListView that has five items that just contain a button, and then five items that just contain a TextView.
Below is the activity code, the activity xml file, and an xml file for each list item type.
OptionsActivity.java:
public class OptionsActivity extends ListActivity {
private static final int LIST_ITEM_TYPE_1 = 0;
private static final int LIST_ITEM_TYPE_2 = 1;
private static final int LIST_ITEM_TYPE_COUNT = 2;
private static final int LIST_ITEM_COUNT = 10;
// The first five list items will be list item type 1
// and the last five will be list item type 2
private static final int LIST_ITEM_TYPE_1_COUNT = 5;
private MyCustomAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MyCustomAdapter();
for (int i = 0; i < LIST_ITEM_COUNT; i++) {
if (i < LIST_ITEM_TYPE_1_COUNT)
mAdapter.addItem("item type 1");
else
mAdapter.addItem("item type 2");
}
setListAdapter(mAdapter);
}
private class MyCustomAdapter extends BaseAdapter {
private ArrayList<String> mData = new ArrayList<String>();
private LayoutInflater mInflater;
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
if(position < LIST_ITEM_TYPE_1_COUNT)
return LIST_ITEM_TYPE_1;
else
return LIST_ITEM_TYPE_2;
}
#Override
public int getViewTypeCount() {
return LIST_ITEM_TYPE_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch(type) {
case LIST_ITEM_TYPE_1:
convertView = mInflater.inflate(R.layout.list_item_type1, null);
holder.textView = (TextView)convertView.findViewById(R.id.list_item_type1_text_view);
break;
case LIST_ITEM_TYPE_2:
convertView = mInflater.inflate(R.layout.list_item_type2, null);
holder.textView = (TextView)convertView.findViewById(R.id.list_item_type2_button);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
}
activity_options.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ListView
android:id="#+id/optionsList"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
list_item_type_1.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_item_type1_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/list_item_type1_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text goes here" />
</LinearLayout>
list_item_type2.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_item_type2_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/list_item_type2_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button text goes here" />
</LinearLayout>
You have two possibilities to do that:
Create a Type and check for your type and return the view related to this type.
BaseAdapter has two methods to check different items in it, getItemViewType(int position) and getViewTypeCount(). Do your stuff there.
Check this tutorial:
ListView with multiple rows
You should create your own class extending BaseAdapter. I recommend watching The World of ListView, it will help you understand everything you need to know about working with ListView.
In addition to #LouMorda answer, I'd use some class, with fields that contains info about item and list item type:
public class Item {
private int itemViewType;
private Object tag;
private String title;
public Item(int itemViewType){
this.itemViewType = itemViewType;
}
public int getItemViewType() {
return itemViewType;
}
public void setItemViewType(int itemViewType) {
this.itemViewType = itemViewType;
}
...
}
So using this object gives more flexibility when adding items to the list in different sequences:
public class OptionsActivity extends ListActivity {
private static final int LIST_ITEM_TYPE_1 = 0;
private static final int LIST_ITEM_TYPE_2 = 1;
private ArrayList<String> mItemsSource = new ArrayList<>();
...
#Override
public int getItemViewType(int position) {
return mItemsSource.get(position).getItemViewType();
}
...
}