I'm trying to add a custom view that I made to an adapter of mine. I'm trying to do this to add a view to merge adapter by commonsware.
https://github.com/commonsguy/cwac-merge
This is my code of me trying to inflate the layout:
LayoutInflater inflater = getLayoutInflater();
LinearLayout row = (LinearLayout) inflater.inflate(R.layout.row,
null);
TextView headerOne = (TextView) row
.findViewById(R.id.titleTextView);
TextView headerTwo = (TextView) row
.findViewById(R.id.titleTextView);
headerOne.setText("One");
headerTwo.setText("Two");
mergeAdapter.addView(headerOne);
mergeAdapter.addAdapter(myArrayAdapter);
mergeAdapter.addView(headerTwo);
mergeAdapter.addAdapter(myOtherArrayAdapter);
This is my xml.
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_weight="1"
android:orientation="vertical" >
<TextView
android:id="#+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-condensed"
android:text="message text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/text_gray"
android:textStyle="bold" />
<View
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#000000" />
</LinearLayout>
Update: Forgot to talk about what my "problem" is. First, is that I've never inflated a layout before so I'm unsure of how it works/whats the proper way to inflate. Second, I get this error:
01-20 23:18:46.427: E/AndroidRuntime(24810): java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
EDIT:
My imports:
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.actionbarsherlock.app.SherlockListActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.commonsware.cwac.merge.MergeAdapter;
import com.google.gson.JsonObject;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.ion.Ion;
import com.eghdk.myapp.R;
import com.eghdk.myapp.util.AppUtil;
import com.eghdk.myapp.util.DatabaseHelper;
public class MyActivity extends SherlockListActivity {
Use two layout resources, not one. Do not inflate a layout, then attempt to take pieces of that layout and use them separately.
Or, to put it another way, the value you pass to addView() needs to be either:
the direct result from inflate(), or
something you create in Java using constructors
try this...
LayoutInflater inflater = getLayoutInflater();
LinearLayout row = (LinearLayout) inflater.inflate(R.layout.row, null);
TextView headerOne = (TextView) row.findViewById(R.id.titleTextView);
headerOne.setText("One");
ViewParent parent = row.getParent();
if(parent != null && parent instanceof ViewGroup) {
((ViewGroup)parent).removeView(row);
}
AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT);
row.setLayoutParams(layoutParams);
mergeAdapter.addView(row);
mergeAdapter.addAdapter(myArrayAdapter);
row = (LinearLayout) inflater.inflate(R.layout.row, null);
TextView headerTwo = (TextView) row.findViewById(R.id.titleTextView);
headerTwo.setText("Two");
parent = row.getParent();
if(parent != null && parent instanceof ViewGroup) {
((ViewGroup)parent).removeView(row);
}
layoutParams = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT);
row.setLayoutParams(layoutParams);
mergeAdapter.addView(row);
mergeAdapter.addAdapter(myOtherArrayAdapter);
Change your below line
LinearLayout row = (LinearLayout) inflater.inflate(R.layout.row,
null);
to
View row = inflater.inflate(R.layout.row,
null);
I think, you didn't add the view to parent
try
yourParent.addView(row);
Where yourParent is the layout where you need to attach this row
Try to remove following line.
LinearLayout row = (LinearLayout) inflater.inflate(R.layout.row, null);
Instead this put following code.
View row = inflater.inflate(R.layout.row, null);
Please follow good practices while inflating layout in android http://www.doubleencore.com/2013/05/layout-inflation-as-intended/
http://www.piwai.info/android-adapter-good-practices/
Related
I have a problem which I cannot understand how to solve.
I have a movie_item.xml which contains a textView and button as component.
my custom ArrayAdapter gets ArrayLists which contain 10 items inside, which means my ArrayAdapter should draw the layout 10 times in my ListView.
Problem is my application textView becomes null when ArrayAdapter works with the layout second time.
Here are my codes:
CustomArrayAdapter.java
package com.example.labb4;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
public class CustomArrayAdapter extends ArrayAdapter {
ArrayList<Integer> movieIDList;
public CustomArrayAdapter(Context context, ArrayList titleList, ArrayList idList) {
super(context, 0, titleList);
movieIDList = idList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//Om vyn används första gången
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.movie_item, parent, false);
}
String title = getItem(position).toString();
int movieID = movieIDList.get(position);
TextView text = (TextView) convertView.findViewById(R.id.TitleTextView);
Log.d("movies","text: "+text+"");
text.setText(title);
text.setId(movieID);
Button button = (Button) convertView.findViewById(R.id.button);
Log.d("movies","button "+button+"");
button.setText("Lägg till");
//Returnera hela Vy
return convertView;
}
}
this is movie_item.xml in res folder
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:orientation="horizontal">
<TextView
android:id="#+id/TitleTextView"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:text="TextView" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
as you see, I use inflate() to work with layout file, and the layout file already contains all components what I need for my job.
But, when I run the program the output is
Boom, the textView becomes null on second time. My app crashes because setText on null is impossible.
But the most mysterious part is if I remove the textView codes from getView on CustomArrayAdapter and print out only Buttons,
public View getView(int position, View convertView, ViewGroup parent) {
//Om vyn används första gången
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.movie_item, parent, false);
}
String title = getItem(position).toString();
int movieID = movieIDList.get(position);
Button button = (Button) convertView.findViewById(R.id.button);
Log.d("movies"," button "+button);
button.setText("Lägg till");
//Returnera hela Vy
return convertView;
}
Button is never null!
I just cannot understand what is making TextView null??
My application works if I make an if statement which checks if test is null or not,
TextView text = (TextView) convertView.findViewById(R.id.TitleTextView);
if(text!=null){
Log.d("movies","text: "+text+"");
text.setText(title);
text.setId(movieID);
}
But I don't think this is a right solution, for me it feels like.. solve the effect, not the reason of the problem..because Log.d shows TextView is null more than 10 times ..
So... why is my TextView is null? How can I solve this?
I already have tried clean and rebuild projects. Restarting android studio didn't help me either.
I threw myself in a task that might be a little too difficult for me.
I'm designing an medical application that displays images of a patient's scan and superimposes several contours that delineate organs.
The patient's scan is a series of PNG images (the background of slices listview rows).
The contours are vectors and a same scan slice may contain several dozens of contours.
To do so, Scan slices are loaded in a listview with custom adapter. Contours are added according to a previously done selection of organs. Contours are imageViews with transparent background added over the scan in a same framelayout. Therefore, imageviews of contours are added dynamically in the layout.
The problem is that I might be asking too much from listview. In fact, I'm getting stuck with the getView method of the adapter. Contours appear, but refresh and iteration through slices seems to be at random.
Could someone throw me a hint about this situation? I'm not sure the dynamic allocation of imageviews is that clever now... What could I do?
Any help would be welcome !
Adapter:
package bhouse.radiovolumes;
import android.content.Context;
import android.media.Image;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
/**
* Created by kranck on 8/3/2017.
*/
public class ScannerListAdapter extends ArrayAdapter<SliceItem> {
private Context context;
private LayoutInflater inflater;
private ArrayList<SliceItem> slices;
public ScannerListAdapter(Context context, ArrayList<SliceItem> slices) {
super(context, R.layout.list_view_scan, slices);
this.context = context;
this.slices = slices;
inflater = LayoutInflater.from(context);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.list_view_scan, parent, false);
convertView.setMinimumHeight(parent.getMeasuredHeight());
holder = new ViewHolder();
holder.scanView = (ImageView) convertView.findViewById(R.id.view_scan);
holder.frameLayout = (FrameLayout) convertView.findViewById(R.id.zoomLayout);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
SliceItem item = getItem(position);
int resIdScan = this.context.getResources().getIdentifier(item.getStorageLocation(), "drawable", context.getPackageName());
Picasso
.with(context)
.load(resIdScan)
.error(R.drawable.borabora)
.into(holder.scanView);
for (int i = 0; i < item.getVectorStorageLocation().size(); i++) {
ImageView imageView = new ImageView(context);
String resourceName = "cylindre__2___" + String.valueOf(position);
int resId = context.getResources().getIdentifier(resourceName, "drawable", context.getPackageName());
imageView.setImageResource(resId);
holder.frameLayout.addView(imageView);
}
return convertView;
}
static class ViewHolder {
FrameLayout frameLayout;
ImageView scanView;
}
}
Layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<bhouse.radiovolumes.ZoomView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" >
<FrameLayout
android:id="#+id/zoomLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/view_scan"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
>
</ImageView>
</FrameLayout>
</bhouse.radiovolumes.ZoomView>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<bhouse.radiovolumes.ZoomView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" >
<FrameLayout
android:id="#+id/zoomLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/view_scan"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
>
</ImageView>
</FrameLayout>
</bhouse.radiovolumes.ZoomView>
</LinearLayout>
I think you make bad usage of getView method
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder holder;
if (convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.list_view_scan, parent, false);
holder = new ViewHolder();
holder.scanView = (ImageView) convertView.findViewById(R.id.view_scan);
holder.frameLayout = (FrameLayout) convertView.findViewById(R.id.zoomLayout);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
// Then do operation here on your view holder
// ...
return convertView;
}
And If you start this project now, think about using RecyclerView instead of ListView.
Now as it is ok with that, you need to clear your Framelayout before adding your ImageViews by calling removeAllViews() method, if not old views remains in it.
I have a RecyclerView with a TextView in it's place as well for when no results are found.
This TextView when calling root.findViewById always returns null, I have tried re-cleaning the project, building the project over again. Nothing has helped.
Here are my imports:
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.mypackage.commoncode.R;
Here is the code for the onCreateView:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_mail, container, false);
//
mProgressBar = (ProgressBar) root.findViewById(R.id.spinner);
mProgressBar.setVisibility(View.VISIBLE);
final Context context = root.getContext();
mEmptyView = (TextView) root.findViewById(R.id.empty_view);
mEmptyView.setVisibility(View.INVISIBLE);
// set list
float ht = BitmapUtils.convertDpToPixel(8, context);
mLinearLayoutManager = new LinearLayoutManager(context);
mListView = (RecyclerView) root.findViewById(android.R.id.list);
mListView.setLayoutManager(mLinearLayoutManager);
mListView.setVisibility(View.INVISIBLE);
mListView.addItemDecoration(new VerticalSpaceItemDecoration(Float.valueOf(ht).intValue()));
mListAdapter = new InboxListAdapter(context);
mListAdapter.setOnInboxClickListener(this);
mListView.setAdapter(mListAdapter);
if (mBackground == null) {
mBackground = new HandlerThread("background", android.os.Process.THREAD_PRIORITY_BACKGROUND);
mBackground.start();
mBackgroundCallback = new BackgroundCallback(this.getActivity().getApplicationContext(), mCurrentKid);
mBackgroundHandler = new Handler(mBackground.getLooper(), mBackgroundCallback);
}
final Handler displayHandler = new Handler(new HandlerCallback(this));
mBackgroundCallback.setDisplayHandler(displayHandler);
//
retrieveInboxList(context);
return root;
}
Here is the XML for the layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="#+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|center_horizontal" />
<android.support.v7.widget.RecyclerView
android:id="#+id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="#+id/empty_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="invisible"
android:text="#string/No_Results_found" />
</FrameLayout>
Any ideas as to why the empty_view TextView is always null?
Logcat error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setVisibility(int)' on a null object reference
at this line:
mEmptyView.setVisibility(View.INVISIBLE);
The view xml referenced does not have the view with the id your are trying to retrieve. Make sure the xml posted is the correct one or that you have another xml for this resolution that maybe is not containing the view.
Being new to Android the following issue drives me crazy, and not being able to Google an answer indicates that the solution is really simple...
I try to add a custom component (ArticleView extends RelativeLayout) to a ViewGroup (LinearLayout) from code but I cannot get access to the ArticleView object, trying to cast to it just throws an
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.eo.read/com.example.eo.read.ArticleInfoActivity}: java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to com.example.eo.read.view.ArticleView
Caused by: java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to com.example.eo.read.view.ArticleView
at com.example.eo.read.ArticleInfoActivity.onCreate(ArticleInfoActivity.java:44)
In my Activity class I do:
package com.example.eo.read;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.example.eo.read.content.Article;
import com.example.eo.read.content.ArticleDB;
import com.example.eo.read.view.ArticleView;
...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_article_info);
_article = ArticleDB.getInstance().getArticle("test");
LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//get the linear layout into which the ArticleView is going
LinearLayout container = (LinearLayout) findViewById(R.id.recommendation_container);
//get the custom component
RelativeLayout ra = (RelativeLayout)inflater.inflate(R.layout.article_view, container, false);
//this causes the classcast exception, although this RelativeLayout really should be an ArticleView
((ArticleView)ra).setArticle(_article);
//adding the ArticleView to the container works fine, and the customizations
//I have made in ArticleView are visible, so indeed it seems ra is an ArticleView ??
container.addView(ra);
}
The (simplified) article_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="260dp" android:layout_height="wrap_content" android:background="#drawable/stroked_grey_plate">
<TextView
android:id="#+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:textSize="16sp"
android:text="Sample text"
android:textColor="#111111"
android:scrollHorizontally="true"
android:ellipsize="end"
android:maxLines="1"
/>
</RelativeLayout>
The layout for the activity contains the id/recommedation_container into which the ArticleView is being inserted. Below is also the same view inserted declaratively, just for clarity:
<LinearLayout
android:id="#+id/recommendation_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="10dp">
<com.example.eo.read.view.ArticleView
android:layout_width="wrap_content" android:layout_height="wrap_content"
custom:titleText="my title text"
/>
</LinearLayout>
The ArticleView class is essentially:
package com.example.eo.read.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.example.eo.read.R;
import com.example.eo.read.content.Article;
public class ArticleView extends RelativeLayout {
private TextView _titleView;
private Article _article;
public ArticleView(Context context) {
this(context,null);
}
public ArticleView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ArticleView, 0, 0);
//in the case where the ArticleView is declared in XML the title is retreived from a custom attribute, this works fine.
String titleText = a.getString(R.styleable.ArticleView_titleText);
a.recycle();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.article_view, this, true);
ViewGroup rl = (ViewGroup)getChildAt(0); //get the RelativeLayout
_titleView = (TextView) rl.getChildAt(0);
_titleView.setText(titleText);
}
//in the case where the ArticleView is initiated from code the title should be set by calling this method,
//which I never can reach since I cannot get to this ArticleView object from my activity :-(
//I realize this class is maybe not fully functional yet but first step is to actually be able to initiate it...
public void setArticle(Article a) {
_article = a;
_titleView.setText(_article.getTitle());
}
}
So, my question is pretty much.. why can't I do:
ArticleView ra = (ArticleView)inflater.inflate(R.layout.article_view, container, false);
and what should I instead do to get to my ArticleView?
Replace ArticleView in your XML file with [packagename].ArticleView
For example, if your ArticleView class is contained in com.john.article, then your ArticleView should be replaced by com.john.article.ArticleView.
If I understand you correctly, you want to add the custom view programmatically and not have it defined in the XML?
If that is the case, what happens if you simply do:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_article_info);
_article = ArticleDB.getInstance().getArticle("test");
LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//get the linear layout into which the ArticleView is going
LinearLayout container = (LinearLayout) findViewById(R.id.recommendation_container);
//get the custom component
ArticleView av = new ArticleView(this);
av.setArticle(_article);
container.addView(av);
}
In case you haven't stumbled upon it yet, it seems this blog has some nice tips regarding custom views: http://trickyandroid.com/protip-inflating-layout-for-your-custom-view/
If you would like to have your Custom view inflated together with your layout, then you can do:
<LinearLayout
android:id="#+id/recommendation_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="10dp">
<com.example.eo.read.view.ArticleView
android:id="#+id/article"
android:layout_width="wrap_content" android:layout_height="wrap_content"
custom:titleText="my title text"
/>
</LinearLayout>
Just taking the XML from your question as an example, not sure how well it fits your situation.
But now, inflating the above XML to a view called, say, root and then doing root.findViewById(R.id.article) should return a view which can be cast to ArticleView.
Thinking about it, if you have an XML file like this:
<com.example.eo.read.view.ArticleView
android:layout_width="wrap_content" android:layout_height="wrap_content"
custom:titleText="my title text"
/>
You actually should be able to inflate it, as you are trying, and cast to ArticleView, since com.example.eo.read.view.ArticleView is now the root of the layout.
Trying to have a ListView (scrollable list) of rows made of two TextViews. I have a list of items from a database that I want to populating into the LinearLayout->ListView->TextView but can't get to the id...
Layout somewhat like this instructional link, but have backed away from RelativeLayout and using LinearLayout to get it working. Not even worried about how it looks yet; just can't get it wired together yet.
http://android-developers.blogspot.com/2009/02/android-layout-tricks-1.html
Have two XML files (very abbreviated details below)
main.xml and stuff.xml
main.xml has
...TextView
...ListView
stuff.xml has
... android:id="#+id/firstLine"
...
android:id="#+id/secondLine"
YES, I do setContentView(R.layout.main); right after onCreate.
Getting null on findViewByID(firstLine) and findViewID(secondLine).
I have an ArrayAdapter where I inflate the stuffView. My thinking and understanding of other examples is it's not inflated (this nested stuffView) until I purposely inflate it. That all works fine but when I do the findViewById it returns null and thus I can't setText().
epic Fail due to complete ignorance/newbieness on my part. Note: I've pored through what I can of Reto's book, especially a simliar example on Page 163 but fail fail fail...
Can some kind soul point me in the right direction?
Must I inflate this nested view? (Reto's example does). If so, what am I missing? I'm hoping someone can point me to a better example. My code's probably too involved at this point to post and a bit proprietary.
Thanks
main.xml
<?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/identText"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="some text here"
/>
<ListView
android:id="#+id/myListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
thing_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="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="#+id/identText"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="some text here"
/>
<ListView
android:id="#+id/myListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
A pojo called Thingy (not copying Thingy.java here - very simple)
The main class: ShowLayoutNicely.java
package com.blap.test;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.TextView;
public class ShowLayoutNicely extends Activity {
ListView myListView;
TextView myTextView;
ArrayList<Thingy> thingys;
ThingyAdapter aa;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myListView = (ListView) findViewById(R.id.myListView);
myTextView = (TextView) findViewById(R.id.identText);
thingys = new ArrayList<Thingy>();
aa = new ThingyAdapter(this, android.R.layout.simple_list_item_1, thingys);
myListView.setAdapter(aa);
// real deal has a call to go find items from database, populate array and notify of change.
Thingy thing1 = new Thingy("first", "first row");
thingys.add(thing1);
// sadly - this isn't triggering getView() which I've overriden...
aa.notifyDataSetChanged();
Thingy thing2 = new Thingy("second", "second row");
thingys.add(thing2);
aa.notifyDataSetChanged();
}
}
The adapter override class ThingyAdapter.java
package com.blap.test;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ThingyAdapter extends ArrayAdapter<Thingy> {
int resource;
public ThingyAdapter (Context _context, int _resource, List<Thingy> _items){
super( _context, _resource, _items);
resource = _resource;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout thingView;
Thingy thingItem = getItem(position);
String identString = thingItem.getIdent();
String nameString =thingItem.getName();
if (convertView == null){
thingView= new LinearLayout(getContext());
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View nuView = vi.inflate(resource, thingView, true);
}
else{
thingView = (LinearLayout) convertView;
}
//here's the problem - these calls return nulls.
TextView row1 = (TextView)thingView.findViewById(R.id.firstLine);
TextView row2 = (TextView)thingView.findViewById(R.id.secondLine);
//and naturally these puke ingloriously....
row1.setText(thingItem.getIdent());
row2.setText(thingItem.getName());
return thingView;
}
}
So this code is in essence what I'm looking for help on; neutered the names to call it Thingy.... This sample isn't triggering the getView(). That's a secondary problem I have to sort out. More importantly, your help on the findViewById failure and if I've got the XML right would help a bunch.
Where you are inflating your layout you can use findViewById on the layout that you are inflating, as I don't know what your code is like here is an example of what I would do:
LayoutInflater li = LayoutInflater.from(mContext);
LinearLayout mLayout = (LinearLayout) li.inflate(R.layout.stuff,null);
View mView = mLayout.findViewById(R.id.firstLine);
You probably want your null to be the parent that you want your inflated layout to have. Hope this helps!
Update
I'd try replacing what you have as:
thingView= new LinearLayout(getContext());
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View nuView = vi.inflate(resource, thingView, true);
with:
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
thingView = vi.inflate(R.layout.thing_item, null);
As you seem to make a new linearlayout for no reason, as your inflation will already be have a linear layout from your xml file. This is pretty much what I said above, and this works for me :)