Object created from layout xml file is null - android

I have two classes that extend the activity class. Each class has it's own layout class, main.xml and compose.xml.
In my main activity I try to access a layout element that is in compose.xml. So:
EditText smsBody = (EditText)findViewById(R.id.smsBody);
But smsBody is null. Why? How can I access it?

Did you set the content view in the onCreate() method?
Like in this example:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

Well, your main activity has a main.xml layout. Your compose activity has a compose.xml layout. Assuming your "smsBody" EditText is in the compose.xml layout, then this will be only accesible in your compose activity, since that widget doesn't exist in your main.xml layout.

when main activity have layout main.xml, how you can expect that you can access component of compose.xml ?? you suppose to play with view inside layout you set using setContentView() .
in exceptional cases we need to use other layouts as well , so you can use LayoutInflater for this

Related

Show View in all my app

I need show a TextView in all Activities, but is much work to do it one by one, because I have +10 Activities.
My objective is when I click in a button, show a textview ("Importing ...") at the bottom of the application. This textview will disappear when I receive a push notification, and I owe a pop up with the response (the pop up also has to appear in any activity).
My project has a custom abstract BaseActivity and all activities extends it.
public abstract class BaseActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
protected void setActionBar(#IdRes int idResToolbar) {
Toolbar toolbar = (Toolbar) findViewById(idResToolbar);
setSupportActionBar(toolbar);
updateFont(toolbar);
}
// ...
}
I think I could use for my purpose but not how to do it.
If anyone has any suggestions I will be happy to hear it.
Thanks in advance.
Use fragments for your content (instead of different activites) you then can add global views to the activity, which holds the fragments.
If you don't want to do that, you'd have to modify the layout(s) in your Base class.
I would suggest you to use a PopupWindow that contains the text view and create a separate class that initializes the PopupWindow on the basis of context given to it.
Now in all your Activities you will have the control of showing and hiding the window as you want. Make sure to make all utility methods required in the separate class to avoid coherence for example hiding and showing the window. setting text of text view of the window and etc.
You can write in onCreate() of your base activity something like
setContentView(R.layout.base_layout);
And in every other Activity at start of onCreate() method, just use super.onCreate()
And more than that to support different layouts add something like this in onCreate() (example for one of activities)
LayoutInflater inflater = getLayoutInflater();
inflater.inflate(R.layout.activity_1_layout,rootGroup)
where rootGroup is a ViewGroup in your Base Activity, in which you will add additional components for every other activity
Create a service, which creates a View which can be drawn over other apps (will require the relevant permission in the manifest)
You could use one of the open source libraries available like this or refer to this example
It's better you use fragments instead of using many activities. However, if you don't wanna do so, I suggest you create a factory which will generate a textview to all activities. Then you must add it into each activity's view.

How the view are refereed under MainActivity In android

Here is the XML code for a simple TextView:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
android:id="#+id/test"/>
Then, in MainActivity, it is used like this:
TextView test = (TextView) findViewById(R.id.test);
test.setText("test");
I want to know how the view is accessed in Main class, which is defined in xml layout.
Can anyone explain how it happens?
how the view accessed in Main class
To be honest, i dont know the process in detail. Let me help you on what i know :
The Activity will search the layout XML in setContentView method.
After the layout has been found, we can use findViewById to link the instance (test - in your case) we created to the layout XML.
If the ID is found, the instance (Java) and XML will be linked.
Of course, you can do something like :
TextView test2 = new TextView(this);
Which means the instance is not must exist in XML.
Sorry English is not my native language.
On your Activity, you have:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
//...
}
According to Android documentation, setContentView is responsible for linking your XML layout to your Activity:
Set the activity content to an explicit view. This view is placed
directly into the activity's view hierarchy. It can itself be a
complex view hierarchy.
After the Activity's content view is set, you can use findViewById in order to access the views of the XML linked to your Activity:
Finds a view that was identified by the id attribute from the XML that
was processed in onCreate(Bundle).
Hope it helps you to understand this process! :)
I think this is the method
1.when you create or declare a text view or something like that a reference is generated in your R file(JAVA file).
2.which is what you access through
R.id.test
this is how your linking works

NullPointerException when calling setText on a TextView outside activity_main.xml

I am making an app using two tabs with different layouts, which means I have three total layouts at the moment:
activity_main,
fragment_receive,
fragment_send
In my onCreate method in my main activity, the following line sets my content view to activity_main. (If anyone could explain why this layout appears to be blank and yet my app still shows both tabs, that would be great.)
setContentView(R.layout.activity_main);
Then I use the findViewById method to set a TextView to a view that appears in both fragment_receive.xml and fragment_send.xml.
currentExchangeRate = (TextView) findViewById(R.id.exchangeRateView);
Then I attempt to use the setText method on this TextView.
currentExchangeRate.setText(Double.toString(lastPrice));
This line gives me the NullPointerException.
Can anyone explain this to me?
findViewById() called from the Activity, looks for the id in the hierarchy of views of the Activity.
if you want to perform that on the Fragment hierarchy, you have to call it from the Fragment view, for example view.findByById() from the Fragment onCreateView, after you inflated the layout.
When you call:
currentExchangeRate = (TextView) findViewById(R.id.exchangeRateView);
The compiler finds that the static int ID does exist within your R.id because you declared them in your fragments, and therefore doesn't throw a compiler error. But at runtime, the current view layout (the one you set with setContentView(R.layout.activity_main);) doesn't hold that ID and therefore returns null.
To access your textview that exists within your Fragment from the Controlling Activity, you use the Fragment Manager (add an id property to your fragments in activity xml, or set tags when you declare your Fragments in your code):
ReceiveFragment receiveFragment = (ReceiveFragment) getSupportFragmentManager().findFragmentById(R.id.receive_fragment);
TextView tv = (TextView) receiveFragment.getView().findViewById(R.id.exchangeRateView);
tv.setText(Double.toString(lastPrice));
findViewById retrieves the view with the requested id from your activity's layout
To get your fragment's textview, make the view that your fragments onCreateView is returning a static variable and initialize it in the onCreateView.
Then you can retrieve the textview like this:
TextView textview = (TextView) YourFragmentTitle.yourFragmentViewTitle.findViewById(R.id.yourId);

What is the difference from inflating an activity and inflating a view in android?

I don't seem to understand if it's possible to inflate (include) an activity into another activity. I know i can inflate a layout xml, this works, but i am wondering if i can inflate an activity. For instance , i have class A that extends Activity and another class B that extends ListActivity. Can i include and use in class A, my class B?
THis is what i have tried:
Class A:
LayoutInflater inflater = (LayoutInflater) MyActivity.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// inflate list
BActivity list = new BActivity();
Class B:
public class BActivity extends ListActivity {
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
List<Model> models= new ArrayList<Model>();
models.add(new Model("John"));
models.add(new Model("Cage"));
setListAdapter(new MyAdapter(this, models));
ListView list = getListView();
}
}
and in xml (the class A xml): (for where i want to see the list)
<view class="com.test.BActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content" > </view>
All of this throws errors :
Error inflating class BActivity
The activities are declared in the manifest.
Do you know what i am doing wrong? this is not the correct way to inflate another activity? I am using Android 2.2 api 8.
Thank you for your time.
Your question title and your issue are not actually the same thing. For completeness, I will answer both.
What is the difference from inflating an activity and inflating a view in android?
The answer is there is no difference. Ultimately, they are the same in process and logic. However, an Activity may have many different Views and you may setContentView() several times to several different Layouts or Views based on your need. An Activity requires a Layout resource, and a View may or may not be a Layout.
Do you know what i am doing wrong?
Yes. Absolutely.
Your code: BActivity list = new BActivity(); is not actually inflating an Activity. You are constructing the Activity, but not starting it.
Your XML defines BActivity as a View, but your code defines it as an ListActivity. These are two different things entirely. A ListActivity has a ListView (extended or otherwise); A ListActivity is not a ListView.
Activity and its subclasses are Contexts that have a Life Cycle that is managed by the OS. They contain and speak to Views of all types, but are not themselves Views.
this is not the correct way to inflate another activity?
No sir, but fear not! The answer is not too far away.
FAKE ANSWER (for completeness) -
First, to start another Activity so that it is inflated, you must call startActivity() from a Context. A Context may be an Application, Activity, Broadcast Reciever or any other app component (Component = declared object in your Android project manifest). So, if you really wanted to start a new Activity, you would change BActivity list = new BActivity(); to:
Intent _listActivity = new Intent();
_listActivity.setClass(BActivity.class);
startActivity(_listActivity);
REAL ANSWER -
However, since you want to see your List in class A, BActivity is not an Activity, it is a View. That means what you REALLY want is to make it recognize your View and this is a different solution. Change public class BActivity extends ListActivity to public class BActivity extends ListView and now all of a sudden you have a custom View!! Now all we have to do is get the List to work.
Constructing the View - Views are different from Activities in that they do not have a public void onCreate(Bundle bundle). All of your stuff from BActivity.onCreate() would instead be placed in the constructor. But, you don't have a proper constructor... hmmm. Well, there are three constructors to choose from -- add one or all of the following (You will probably want either option 1 or 2, at first. But you won't use both at the same time hint hint, read the comments:
//This constructor is used when the View is created from code (not XML!!)
public BActivity(Context context)
{
}
//This constructor is used when the View is created from XML (not code!!)
public BActivity(Context context, AttributeSet attr)
{
}
//This constructor is used when the View is created from XML with a Style defined in separate XML.
public BActivity(Context context, AttributeSet attr, int defStyle)
{
}
Inflating the Activity = Inflating the View
You have a choice here, you can either add the View, or you can inflate the View. There are many options for both. Based on your question, I shall assume you want to inflate the View. Simply change BActivity list = new BActivity(); to setContentView(R.id.MyXML). MyXML, of course, would be the name of your XML Layout file. SetContentView will then open the appropriate View for you (BActivity) using the 2nd constructor from the list above.
Understanding the difference between View and Activities is important. The processes between them are very similar, but they themselves have a intertwined but separate purpose.
An Activity MUST have a View.
A View MUST be in a Context.
An Activity is a Context, but a Context may also be one of several other possible classes.
Both may be inflated using a LayoutInflater
An Activity has a convenience method called setContentView which can inflate an entire XML file.
A View must inflate each View manually using LayoutInflater object.inflate().
An Activity has a Life Cycle. A View has a draw cycle instead.
For more information, certainly read more on the Android Developers Resources. However, some of these things are only learned by experimentation.
Hope this all helped!
FuzzicalLogic
Inflating means parsing an XML description of an object and building a Java object with the described attributes. Activities do not have a detailed description in XML and thus no point to inflate them.
You can dispatch activity A from activity B or you can use the new concept of Fragment to combine multiple sub activities into activities.
BTW, you can define custom views (by subclassing one of the view classes) and use it in your XML layouts, just put the class full path e.g. in the layout instead of let say .

Setting global Button and EditText objects

I'm getting null pointer exceptions when I try to initialize Button and EditText objects in global scope, can't figure it out. I've commented out everything but the bare minimum for the app to display my layout, but this still causes a crash:
private EditText addmoney = (EditText)findViewById(R.id.addmoney);
R.id.addmoney definitely, definitely exists. So what the heck? Is it impossible to declare EditText in global scope? I need to be able to call it from both onCreate and onPause in a class extending Activity, is there maybe another way I should be doing this?
EDIT:
I tried using shade's method of inflating the layout first but it causes errors, apparently your not allowed to use system services before onCreate() has been called and inflating a view requires one.
You have to execute findViewById only after you have set the content for your current activity.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
addmoney = (EditText)findViewById(R.id.addmoney);//it knows in which file to search for the id
}
Alternatively, you could do something like this:
private View dummy = (View) View.inflate(this, R.layout.dummy, null);
private EditText addmoney = (EditText) dummy.findViewById(R.id.addmoney);
... and in the onCreate (or wherever else):
setContentView (dummy);
Since you already have the parent of the EditText view instantiated, you can reference it without having a NPE.
NOTE: The first parameter of inflate is a Context. Therefore, you need a Context that is alive for this to work.
Ooops, wrong class :D

Categories

Resources