Android: Adding layout to a different activity's layout - android

Currently trying to add a layout (box.xml) to my main layout (activity_main.xml) from a different activity, but having trouble correctly doing this. Here is an example of what I'm trying to do:
(Note: removed params for simplicity)
activity_main.xml
<FrameLayout>
<ScrollView>
<LinearLayout>
<!--include layout="#layout/box"-->
</LinearLayout>
</ScrollView>
</FrameLayout>
box.xml
<TableLayout>
<TableRow>
<TextView/>
<ImageView/>
</TableRow>
<TableRow>
<TextView/>
<Button/>
</TableRow>
</TableLayout>
CreateNewBoxActivity.java
(Note: My MainActivity.java calls startActivity(new Intent(this, CreateNewBoxActivity.class)))
public class CreateNewBoxActivity extends Activity {
private ImageButton mFinish;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_newBox);
mFinish = (ImageButton) findViewById(R.id.btn_finish);
mFinish.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
//add box.xml where <include layout> is located in activity_main.xml
finish(); //close this activity and back to main activity to see
//added box layout
}
});
...
}
}
Thanks for any help on how to add this layout! Not sure the best way to tackle this.

You will want to use a LayoutInflater to inflate box.xml. Make sure you have an id for the LinearLayout that you want to add the box.xml to. Inflate that layout with something like
LinearLayout ll = (LinearLayout) findViewById(R.id.llId);
then you can use addView to add the box layout to your LinearLayout.
See this answer for a more detailed example
Edit
After further discussion, the OP wants to add certain elements from the layout in the second Activity to the layout used in the first Activity. This would be accomplished easier by using startActivityForResult() and passing back the data to the first Activity.
Then, in onActivityResult() in the first Activity the appropriate layout can be added to the original layout using the previously mentioned approach (inflating and calling addView()).
How to handle the data and what needs to be added depends completely on how this is handled by the dev. Data could be added to a model class from the second Activity then checked and added in onActivityResult() or this same method could check for Intent data passed back through setResult().
Intent Docs contains an example and the method needed to pass data back.
This answer has a brief example of using startActivityForResult() and passing back Intent data.

Related

Put a ListActivity "in" my main activity view

I will try to phrase this question more succinctly:
Say I have a completely functioning ListActivty say .. say, GreenListActivity.
How do I "put that" GreenListActivity inside another existing activity layout ? Thanks!
My android MainActivity has an xml file activity_main.xml, like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.client.app.MainActivity">
// some other images, buttons widgets, etc here
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_container"
xmlns:android="http://schemas.android.com/apk/res/android">
<ListView
android:id="#+id/feedView"
android:layout_width="wrap_content"
..etc..
android:scrollbars="none"/>
</android.support.v4.widget.SwipeRefreshLayout>
// some other images, buttons widgets, etc here
</RelativeLayout>
It all works well, the table is complex, everything works great. So simply IN MY MAIN ACTIVITY, I have...
feed = (ListView) findViewById(R.id.feedView);
superDap = new SuperAdapter(this, getLayoutInflater());
feed.setAdapter(superDap);
superDap.notifyDataSetChanged();
and all the other code relating to the table and cell handling.
Now, I roughly understand ListActivity so I've made a new class...
public class MainFeedActivity extends ListActivity
I did put that in the manifest.
Now, I understand that generally in the main activity, I will launch the new list activity like this:
Intent feedIntent = new Intent(MainActivity.this, MainFeedActivity.class);
startActivity( feedIntent );
My confusion,
Question one, in activity_main.xml what do I do to tell it that where I currently have <ListView android:id="#+id/feedView" in fact I want to "put in" my new MainFeedActivity ?
Question two in fact what should the xml file for MainFeedActivity be like? (Should there be one??)
Sorry, I found many great tutorials fully explaining "how to make a ListActivity",
but,
much to my shame I can't learn how to "put that list" inside the main activity page. That is to say "in" the xml of the main activity. Or am I just doing it all wrong? (Should the list NOT BE a new activity, maybe?!!) Thanks for any pointers! Phew
I think you're a bit confused about what should be done.
If i understand correctly you have a MainActivity, which somehow navigates to a different activity that has a list.
Your main activity has an XML file which defines its own layout, which represents the home screen.
Your FeedList activity which has a different XML that defines its layout as well.
Those two are different and separate from eachother, when you navigate from HomeActivity to FeedList activity using intents as you mentioned, your new activity will be launched and it's XML will inflated and presented on the screen, so there is no need to put the list 'in' the home activity.
Note: use a normal Activity not a ListActivity and define the ListView you want in the xml of that activity.
feel free to ask if anything is unclear
A ListView can be shown using different methods.
You might use a ListActivity or a ListFragment (if you are to use Fragments).
In this case, the list hase to be named list (android:id="#android:id/list").
Android will recognize it and manage it.
OR (and I do prefere this one), use a ListView in your design.
In this case the ListView can have any id (such as android:id="#+id/feedView").
Now you have to thell Android to finde the ListView by id.
In the same activity where you have the ListView, you then programmatically create an adapter, fill it and assign it to your ListView.
I hope I cleared your doubts (at least in part).
Anyway, here's a great tutorial on ListViews by Lars Vogel: http://www.vogella.com/tutorials/AndroidListView/article.html
This is how the xml file should be built:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="209dp" >
</ListView>
<TextView
android:id="#+id/group"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
//add any additional widgets here
</LinearLayout>
In the classes, I would use fragments to implement the above:
public static class MainFeedFragment extends ListFragment {
public void onStart() {
super.onStart();
// selecting single ListView item
ListView lv = getListView();
// Lauching the Event details screen on selecting a single event
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting values from selected ListItem
String ID = ((TextView) view.findViewById(R.id.leader_id))
.getText().toString();
Intent intent = new Intent(view.getContext(),
CoreTeamDetails.class);
intent.putExtra(pid, ID);
view.getContext().startActivity(intent);
}
});
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main,container, false);
//added code to show how adapter connects to list
ListAdapter adapter = new SimpleAdapter(getActivity(),membersList,R.layout.coreteam_item,
setListAdapter(adapter);
return rootView;
}
}
Hope this helps you.

Issue with using an xml for a second activity (R.id issue)

Hey guys so I'm a bit new to Android programming and I have an issue and need help.
So I'll use the first app that the official android site uses for training (http://developer.android.com/training/basics/firstapp/starting-activity.html)
and I'm confused about the creating second activity part. So after they've passed the intent they create a new TextView using java code (instead of XML) so I tried creating that TextView using the xml. I created a new TextView in the xml for the second activity and I give it an id like this:
<?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"
tools:context=".DisplayMessageActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world"
android:id="#+id/new_Text"/>
</LinearLayout>
and here's the java code for the second activity:
package com.example.myfirstapp;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.MenuItem;
import android.widget.TextView;
import android.support.v4.app.NavUtils;
public class DisplayMessageActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the message from the intent
Intent intent = getIntent();
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
// Create the text view
TextView textView = (TextView) findViewById(R.id.new_Text);
textView.setTextSize(40);
textView.setText(message);
// Set the text view as the activity layout
setContentView(textView);
// Show the Up button in the action bar.
// getActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
}
All the code worked fine before I changed it. I changed
TextView textView = new TextView(this);
to:
TextView textView = (TextView) findViewById(R.id.new_Text);
but for some reason it can't find new_Text and Eclipse only suggests id's from my main.xml. Why is it that way? Is it because R.id.blabla only gets id's from main.xml? So am I forced to make layouts using java code if they're not going to be from main.xml?
Alot of confusion in this post, but for starters:
Each Activity that you intend to eventually be visable to the user gets its own XML layout. If you start a new Android project it will give u by default 1 XML layout located in the res>layout folder and 1 activity which will serve as your user facing visual activity by default.
For your purposes , some easy ways to figure out if a activity is meant to be a "visual" activity include:
*it extends activity or some other android superclass
*it has a "onCreate method (useually located towards the top of the class)
*inside that onCreate method there is a line of code called setContentView that looks something like this.
setContentView(R.layout.httpex);
The setContentView method is important bc its kind of like the glue between your activity and your xml layout. After R.layout.___ goes the name of the XML layout you would like to use.
Only after youve set your content view to the approprate view can you link the elements or "views" from ur xml layout to your activity using the id you created. like this
TextView textView = (TextView) findViewById(R.id.new_Text);
if you set the content view to httpex.xml , you can only link to views inside httpex.xml and ect...
I have a spft spot for newbs bc ik what dicks this crowd can be to new blood for their ignorance , they forget how hard it was starting out and begin to feel all this stuff is common sense and obvious, but if i were you i would head over to thenewboston[dot]com and watch the entire series before posting to many questions like this around here so you dont get flamed on.
You can only call the widgets after you have set up the view to a particular XML for your activity. For example if you have an activity call Main you will use one XML as the UI for that particular activity, so you can call widgets created in that particular XML. As you did not post your code I can only guess that you are trying to generate a second XML with the TextView and then just calling it.
At the beginning of the Activity when you set up the layout that's the XML from where you can call the widgets from, unless you inflate the view to call a second XML that is not your case I suppose.
I hope I understood your question correctly.
Add setContentView() method before findViewById() method.

Using GlSurfaceview in activity

I have an Activity and i had set activity's content view as "R.layout.main.xml".And i have an another class which contains animation created using openGL. Now i need to use this animation in the background of the Activity.
The code is like this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_pixie);
mGLView = new ClearGLSurfaceView(this);
setContentView(mGLView);
}
But my app is Crashing ..How can i solve this.
When you call the setContentView() a second time, you replace what had been set the first time, leaving you with only the background. The crash is most likely because you depend on the elements in the main layout, which is removed.
Rather than calling setContentView() twice, you should include the GLSurfaceView in the main layout. Below is an example of how this can be done:
<?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>
<your.application.package.ClearGLSurfaceView
android:layout_width="match_parent"
android:layout_width="match_parent"/>
<!--put the rest of your layout here, i.e the contents of the original R.layout.main_pixie-->
</FrameLayout>
Then you can load this layout in your onCreate() as usual (main_pixie_new refers to the above xml, I just gave it that name to keep things as clear as possible):
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_pixie_new);
}

How can I access views in activities within a TabActivity?

I've got a TabActivity containing other activities intended to split up a form. The TabActivity has in its layout a button intended to collect the data from all the form-related views across all the activities contained within the TabActivity and store it. The problem I'm running into is that the TabActivity doesn't appear to have access to these views; when I call findViewById() with one of them, I get a NullPointerException.
The documentation seems sparse about exactly how TabActivity works with respect to controlling the activities it contains. If it destroys an activity when switching from it to a different one, the situation I'm in would make sense. I'd like to know the best approach for accomplishing the goal described above.
src/com/vendor/MyTabActivity.java:
public class MyTabActivity extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_tab_activity);
final Button saveButton = (Button) findViewById(R.id.save_button);
saveButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// NullPointerException happens here
String fieldValue = ((TextView) findViewById(R.id.text_field)).getText().toString();
}
});
}
}
res/layout/my_tab_activity.xml:
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost">
<LinearLayout>
<TabWidget android:id="#android:id/tabs"/>
<FrameLayout android:id="#android:id/tabcontent" />
<Button android:id="#+id/save_button"/>
</LinearLayout>
</TabHost>
src/com/vendor/NestedActivity.java:
public class NestedActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.nested_activity);
}
}
res/layout/nested_activity.xml:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout>
<EditText android:id="#+id/text_field"/>
</RelativeLayout>
</ScrollView>
Your problem comes from these two lines in MyTabActivity...
setContentView(R.layout.my_tab_activity);
...and...
String fieldValue = ((TextView) findViewById(R.id.text_field)).getText().toString();
...although you obviously know the findViewById(R.id.text_field) is what's causing it.
Using findViewById(...) only works when trying to access UI elements which have been inflated as part of your current Activity. As there isn't a TextView with the resource id of R.id.text_field in the my_tab_activity.xml, it's never going to work.
Accessing activities which are tab content from the TabHost / TabActivity is tricky. My suggestion would be to use SharedPreferences which can be accessed from everywhere in your app. Once a TextView (or any other user-input item) is changed, save it to a SharedPreferences using a 'key' which identifies which activity/tab it came from. From then on, the TabActivity can collate the data easily.
You can get a reference to activities running inside of the tab activity using getLocalActivityManager() or getCurrentActivity(). For the activity object you get back you can do activity.findViewById() to get a reference to a view inside of the specific activity. But to point out TabActivity has been deprecated and you should be using Fragments to do what you are looking for. If you are targeting a version of Android earlier than 3.0 you can use the compatibility library to access fragments.

layout with fragment and framelayout replaced by another fragment and framelayout

EDIT:
So after the comments below, I revisted and realized what was hanging me up.
Imagine my client list and client details activity be started by :
public class ClientsMainActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//StudioTabOpenHelper db;
setContentView(R.layout.main_client_activity);
}
}
So this works great, starts up my main_client_Activity (defined in a layout below, and i call this activity when a button on my main screen is clicked):
Intent intent = new Intent(getActivity(), ClientsMainActivity.class);
startActivity(intent);
Easy the issue is, the ClientsMainActivity does not call a OnCreateView or anything, just sets the layout to the layout that defines my Fragment, and my ListFragment. This is fine cause I am not trying to pass anything into the ClientsMainActivity, but if I have a hypothetical activity like:
SessionMainsActivity that is called when they click on the session edit of a client, then I would not be calling the SessionsMainActivity the same way (starts activity that just sets to alayout), i would want that layout set as it defines how my fragments are split up. But I would also want to pass in data to that and then to the subsequent fragments (like which session they clicked on to be editing/mucking with.
So I wonder if the above makes sense, I am sure its a simple thing I just cannot wrap my brain around. I have no issues calling FragmentActivities from other fragments, they take up the whole screen but it works. So I guess the big issue is that ClientsMainActivity is from some example I found online for doing recipes that shows you how to make multiple fragments to a screen. The thing that gets me all that FragmentActivity does is sets the content view, to a layout that does all the work it seems, so that's why I cannot figure out how I would code it to do the same thing but let me pass in values to the fragments the layout defines etc...
END EDIT
So I am using this nice little tutorial here:
http://developer.android.com/guide/topics/fundamentals/fragments.html
It has gotten me a long way and utilizing what they say to do for the main activity, and the fragment_layout.xml, I got a nice client list on the left (Thats a listfragment) and a details fragment on the right.
Then i added the ability to edit session information on a client (or edit client details) both of which were full screen fragments. This worked great.
Now I decided my Session edit ui would best be served splitting the information up into two panes again.
This is not working as I thought, like I said I have a main_Activity that does this in the onCreate:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_client_activity);
}
with the main_client_activity.xml being defined in two layouts but the one for landscape tablets is here:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.viciousbytes.studiotab.subactivities.ClientListView"
android:id="#+id/client_list" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent" />
<FrameLayout android:id="#+id/client_details" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground"/>
</LinearLayout>
This all works great! In which case I handled everything else as a full screen activity that started its own fragment:
EditSessionActivity
EditClientActiivyt both of which use getSupportFragmentManager().beginTransaction and I could pass information into it from the .newInstance call.
I had my session_edit.xml layout defined with buttons, textviews etc..and that was working great. Thats what i loaded in my SessionEdit fragment "launched" by my EditSessionActivity But now since I want to split it apart I ran into a snag. Above I defined a client_list and a client_details id, are these placeholders on my screen? do I reference those when I wanna replace whats there with totally different fragments?
or do i build another fragment layout called something like fragment_session_layout which defines something like:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.viciousbytes.studiotab.subactivities.SessionEdit"
android:id="#+id/session_edit" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent" />
<FrameLayout android:id="#+id/invoice_details" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground" />
</LinearLayout>
Sorry don't know what to title this on the tip of my tongue of what I am asking, basically how to get two panes of fragments twice over. THe demo online shows how to do one (and a simple ListFragment at that).
I have done all the above and I just cannot figure out how to pass into the fragment the data I need, I was using this in my EditSessionActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int clientID = getIntent().getIntExtra(THE_SELECTED_CLIENT, -1);
int sessionID = getIntent().getIntExtra(SELECTED_SESSION,-1);
SessionEdit edits = SessionEdit.newInstance(this.getBaseContext(), false, clientID, sessionID);
mUIListener = (OnUpdateUI)edits;
getSupportFragmentManager().beginTransaction().add(android.R.id.content, edits).commit();
}
that worked, but to try to adhere to the earlier fragment example, i assumed my EditSessionActivity was sorta like making another MainActivity (cause it has two panels in it like the main one). so I recoded the onCreate in EditSessionActivity with this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_session_fullview);
}
Which after fighting in my EditSession fragment dealing with the onCreateView, I got this to finally work but couldn't pass in the data cause there is no instantiation of the object using like the previous onCreate which had the edits=SessionEdit.newInstance(...)
So is it good practice to be doing the other fragment layout that has two pains in it and starting that up when the right action is triggered. Or is one supposed to replace the two already created fragments?? from my main_client_activity.xml somehow?
I assume editing clients and editing sessions are two distinct activities. When you switch from "editing clients" to "editing sessions" mode, both the "list" and "details" panes would change?
I would go with two layout files, instead of trying to reuse the same layout and reload fragments in it.
If you tried to reuse the same layout, you would have to:
Change #+id/invoice_details to something like #+id/right_pane. Otherwise it would look confusing to load something related to sessions into "invoice_details" placeholder.
replace fragment definition with another FrameLayout and load either ClientListView or SessionListView (or however it's called) fragment there at runtime.
This would add more complexity than having another layout xml file in my opinion.
So
Take your existing code that works with client list and client details
Duplicate all involved parts, and change what needs to be changed so it's now session list and session details
Remove duplication where it's easy to do (common functions go to utility classes, common layout elements to layout includes). Leave the things that are hard to de-duplicate as-is.
Re-evaluate later, when you have more fragments, more layouts and more experience.
UPDATE, about two different approaches fragments can be embedded in activity
As the Android documentation states, there are two main ways you can get a fragment to show up in your activity:
declare the fragment in layout's XML file (<fragment class=.... />)
put a placeholder FrameLayout in layout's XML file and load fragment at runtime
First approach is fine when fragment doesn't need to receive any arguments. Like, for example, if the logic to retrieve single and only list of clients is hardcoded in fragment's code.
Second approach lets you pass arguments to the fragment, and therefore is appropriate for "details drilldown" type of fragments.
From updated question I understand that,
each client has a separate list of sessions
the components in play are: EditSessionActivity that hosts two fragments, one for displaying list of sessions, another for displaying session details
If that's correct, then indeed you'd need to load both fragments programmatically because both needs parameters to be passed to. So your layout would have two FrameLayouts. The EditSessionActivity would start with getting some parameters from intent ("which list of sessions are we working with?"), and load "list of sessions" fragment with these parameters. When user selects list item in that fragment, the other fragment would be loaded with session details.

Categories

Resources