Why is
TextView test = (TextView) findViewById(R.id.testTextView);
test.getText();
generating a null pointer exception? The id is correct, testTextView is correctly declared in my XML layout file.
The only reason for findViewById to return null if you are passing a valid id is that you are either setting the wrong content view (with setContentView) or not setting a content view at all.
I think you might have written setContentView(..) after defining the TextView. Reverse these, and it should work.
Change:
TextView test = (TextView) findViewById(R.id.testTextView);
.
.
setContetView(..)
To:
setContetView(..)
.
.
TextView test = (TextView) findViewById(R.id.testTextView);
You probably haven't called setContentView. You can only use findViewById to get elements of views that have already been inflated.
You could also use a layoutinflater to inflate the view, but that's probably not what you want.
Are you sure the TextView is set on the right XML?
For example if you're creating a Dialog that loads a custom XML, to get an element from that xml you have to mention it in dialog.findViewById(R.id.testTextView);
Like Falmarri said, the view has to be inflated.
I understand you solved it by creating a new project, but still thought to mention it for future users.
It can also be that you defined the activity in two files. For example layout and layout-v21 and some information like id is missing on one of them. So check all the activity's layouts
In my case, the layout was not finished inflating. Solved by adding a small delay before trying to access the TextView.
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
TextView test = (TextView) findViewById(R.id.testTextView);
test.getText();
}
}, 100);
I struggled with this for a while and what I realized was, that, if you have more than one layout file version like:
"activity_one.xml" in "layout" folder and one in "layout - small" folder
Which I used for multiple phone layout support, the problem was that one of the TextViews was in both, with the exact same ID and everything, however the difference was that one was higher up in the hierarchy of views in the layout.
When I changed them to be in the same spot it worked.
(I know this is already answered, but maybe this helps someone out there. Very rare though.)
Related
I need to show a "No data found" message on many screens in my app. For that I created a separate layout with message and image; Now,I'm not sure whether I should include that layout in all other activities' layout or render this layout at runtime? What would be more efficient? Any suggestion is appreciable.
Thanks;
I use a textview with text : "No data found" in all layouts and set VISIBILITY GONE or VISIBLE according to api result.
Or you can add view to your main layout if no data found. Like this;
public showAlert(LinearLayout layout){
TextView textView= new TextView(context);
textView.setText("No data found");
layout.addView(textView);
}
Write this function in a class and call everywhere you want
I want solution of following:
I have create xml file in data/data/com.example.file/files/abc.xml so during running of app how I get this abc.xml in res/layout and should display on screen.
Thanks.
In general, the XML vocabulary for declaring UI elements closely
follows the structure and naming of the classes and methods, where
element names correspond to class names and attribute names correspond
to methods.
Courtesy goes to #Mike M : You cant create this .XML files used for layouts are pre-compiled .
I'm not sure I have followed your question- are you trying to attach a child view to the RelativeLayout? If so you want to do something along the lines of:
RelativeLayout item = (RelativeLayout)findViewById(R.id.item);
View child = getLayoutInflater().inflate(R.layout.child, null);
item.addView(child);
the RelativeLayout item will be the container for your child view.
Your question needs to be a bit more specific, but here's a general answer:
If you are using fragments then you should re-create your fragment and then use:
inflater.inflate(R.layout.abc, container, false);
If you are using activities then you should use:
setOnContentView(abc);
Short Story:
I have a layout "layout.xml", which gets replaced by another layout "success.xml" after a successful web request. Both layouts have an ImageView that provides the backgrounds to the layouts. These 2 backgrounds both need to be the same, and both are dependent on a user preference.
Longer Story: This all happens in a Fragmnet with an AsyncTask replacing the contentView with "success.xml" in onPostExecute after the web request. This happens as follows:
View view = getView();
view = null;
view = View.inflate(context, R.layout.success, null);
What I tried to do is give both ImageViews the following android:id="#+id/background_image" and then call
ImageView background = (ImageView)view.findViewById(R.id.background_image);
background.setImageResource(R.drawable.bg1);
This background-setting works for the initial view (layout.xml), but on trying to change to "success.xml", I get a NullPointException because background is null.
I've checked and the View's id is set to -1 while the original view's background_image id is set to something sensible and valid.
I've also tried setting the second view's background id like this: android:id="#id/background_image", i.e. without the '+', but still no luck.
The added complication is that it's not just 2 layouts, but about 5 that I need to do this for, so it would be really handy to recycle view id's.
Any help would be greatly appreciated.
Your code for replacing the fragment's view will not do what you want, the original view will remain the same as you change only a reference to that view and not the actual object.
To replace the view of the fragment with the new layout you could have another ViewGroup(for example a FrameLayout) in the basic layout (layout.xml) wrapping your current content(don't forget to give it an id) of layouts.xml(as I understand this is the basic layout). Then, when it's time to replace the layout you could simply do:
// remove the current content
((ViewGroup) getView().findViewById(R.id.yourWrapperLayout)).removeAllViews();
// add the new content
View.inflate(context, R.layout.success, ((ViewGroup) getView().findViewById(R.id.yourWrapperLayout)));
You could avoid adding an extra layout if, by any chance, all your five layouts have the same type for the root view(like a LinearLayout etc). In this case you would use the same code as above but you'll modify the other layouts file to use a merge tag. Also, you'll be looking for the id of the root in the layout.xml layout into which you'll add the content of the other files.
Then you could have the same ids, but you'll have to reinitialize any reference to the views(meaning that you'll have to search for the view again if you store a reference to the view(like a Button field in the fragment class)).
I'm wondering if anyone can shed some insight as to the best practice for dynamically creating controls (inflate vs instantiate).
Inflate:
TextView styledText = (TextView)inflater.inflate(R.layout.styledTextView);
Instantiate:
TextView styledText = new TextView(mContext);
styledText.setTextAppearance(R.style.StyledTextStyle);
The object being created can either contain attributes in the inflated XML file, or be contained in a Style definition which is added to the instantiated object afterwards. (Assume that this styling includes width, background, text color, etc).
Haven't been able to run any time/memory tests of each method, was wondering if anyone knew which was quickest/most efficient.
LayoutInflator has a slight overhead because it has to parse xml in order to build the object. It also temporarily takes more memory for the same reason. Other than that, it builds the View object in the same manner that you would anyway. It may be something to worry about if you call it hundreds of times a second for some reason. 99.9% of the time though you'll never know the difference.
Also to note, any method that accepts an xml resource like "setTextAppearance" will have the same xml parsing overhead. The only difference in the examples you provided is it's not parsing the TextView xml, but it would still have to parse the style attributes.
Though this post asks about controls specifically, I think it's relevant to note that .. for working with a layout you want to dynamically create/add, I found in using the new (aka instantiate) approach , I was not able to get a reference to an inner ImageButton element that was defined in the xml file for which I instantiate the layout object reference.
When I use the inflate approach, the ImageButton was present upon reference.
So in my case:
Works :)
LayoutInflater inflater = LayoutInflater.from(getActivity());
CardView myCardView = (CardView) inflater.inflate(R.layout.my_cardview, null);
ImageView icon = (ImageView) myCardView.findViewById(R.id.iconId);
~~~~~~~~~~~~
Don't Work :( .. variable icon is null in this case
CardView myCardView = new CardView(getActivity());
ImageView icon = (ImageView) myCardView.findViewById(R.id.iconId);
As mentioned in topic, I have some Views, e.g. a TableRow with always the same background used as topic, or a special TableRow containing a TextView with some special styles/properties. These Views are set dynamically, so it's problematic to use a XML for this. As I read it's not possible to set styles programmatically too. So what's the best way to solve that?
Possibility 1:
I use and instance derived Views, like this:
public class TopicTableRow extends TableRow {
public TopicTableRow(Context context) {
super(context);
setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
setBackgroundColor(Color.parseColor("#777777"));
setClickable(false);
}
}
Possibility 2:
I could create a valid xml template with a special layout I never use in the application, containing the needed Views which have already all assigned styles. Afterward I access the needed Views by R.id....
But this method seems to be very dilettante to me.
I don't think that those 2 possibilities are the "real" Android way to do this, so how is this usually done?
If you want to set specific styles for groups of elements, you can use the themes and styles concepts in android.
You can read up on them here: http://developer.android.com/guide/topics/ui/themes.html
It is not possible though to change the style attribute of a view programatically.
Therefore the android way is probably to create the Views you need in XML and use a LayoutInflater to get create an 'java' version of the xml view. This allows you to reuse the component and fill it with apropriate data for as many rows as you would like.
Button view = (Button) LayoutInflater.from(this).inflate(R.layout.textViewFromWeb, null);
I hope this will be of use to you!