Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Josh Savage
1,817 PointsAndroid | Multiple Page Application
Hi Ben Jakuben,
I have kinda asked you this question before but I wanted to create a thread so people in the future can get help.
Basically, I want to create a menu driven application (kinda similar to BlogReader). I would like a menu as the main activity, then each list item links to another page with different content.
I'm wondering do I have to create a new activity class and a new XML for each page or is there a clever way of creating this kind of application.
Thanks in advance!
11 Answers
Ernest Grzybowski
Treehouse Project ReviewerIdeally each activity will have a corresponding layout file for said activity. If I have an application with a main screen with four buttons, and each button will take you to a different part of your app, I will most likely have 5 activity files and 5 layout files.
Ben Jakuben
Treehouse TeacherI'll paste in my answer to your other question just for reference, but let me know if you have any follow up questions to this.
--
A menu as a list would probably be represented in a ListView (see the Blog Reader Android project). Tapping on a row in the list would open up a different page where you could load whatever content you want based on the app. Again, in the Blog Reader project, we tap and link to a separate page (it's called an Activity in Android) that displays blog posts inside a WebView (kind of like an iframe). If you are playing videos from the list, you could actually very easily link to an external video player using something called an Intent that sends you over to whatever video player is installed on the device.
As Ernest mentioned, the other Activities you link to will need their own layout files.
Josh Savage
1,817 PointsThank you.
So similar to how a web page works, I have and activity and a view for each 'page'. Isn't that a little demanding creating all those classes?
Next how would you check to see which row was selected to load the correct activity?
(I thought maybe you could have a class that would call the necessary content.)
Thanks
Ben Jakuben
Treehouse TeacherThis is cool - you are getting into some good app design territory!
First to answer your easy question: You check the row in a method called onListItemClick. Thanks to the handy dandy forum mini profiles, I see you haven't gotten that far in the Blog Reader project. It's in the last stage, so that should help you. You can download the project code ahead of time if you want to see how we do it.
Now, it can be a little demanding to create all those classes. But this is where your data and app architecture come into play. What are those other activities doing? Are they similar? Are there parts you can reuse? This is where development veers into art as opposed to science.
So let's say your list has four menu items. Two display detail information of some sort, one plays a video, and one is a form. You would need separate Activities and layouts for each one, but you might be able to reuse the same Activity and Layout for the "detail" pages if they are displaying things in the same way. You could just send different data in the Intent extras (see that last stage again for info about Intent extras).
Josh Savage
1,817 PointsOk but would I use a switch statement or something to say if item1 is selected - open item1 activity?
I understand the concept but writing the code is another story :)
Basically my app is slightly different in that each list goes to a activity with different content, the functionality of the activity is exactly the same. Any chance you could explain in as simple as possible how i would click on a list item > check to see which item was selected and run the intent that starts a new activity and loads in the appropriate content :)
Thank you so much :)
Ben Jakuben
Treehouse TeacherThe onListItemClick method has position as one of its parameters, and you use that to tell what was clicked. So yeah, then you could use a switch statement or whatever to start a specific Activity.
Based on what you've written, I would write the switch statement to set the class name of the Activity, like this:
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Class targetActivity = null;
switch(position) {
case 0:
targetActivity = MainListActivity.class;
break;
case 1:
targetActivity = BlogWebViewActivity.class;
break;
}
if (targetActivity == null) {
// prevent crash
Log.wtf("WTF", "Why am I here?");
}
else {
Intent intent = new Intent(this, targetActivity);
startActivity(intent);
}
}
Josh Savage
1,817 PointsAwesome thanks.
Just wondering is this the way you would do it? or recommend doing it? I am pretty new to the programming concept, so would appreciate the feedback :)
Also how could I reuse the same activity to call in the content appropriate to the list row? So for example how would I check on the other activity what value the intent has and then load the XML appropriate to that?
I don't know if this is the best way to do. So please say if you think there is a better way :)
Thanks!
Josh Savage
1,817 PointsHey Ben Jakuben
I have copied your switch statement above.
This is mine:
Intent myIntent = null;
switch (position) {
case 0: // linearlayout / scrollview // hide actionbar using manifest.
//bundle passes values from one activity to another
myIntent = new Intent(v.getContext(), Page.class);
Bundle b = new Bundle();
b.putLong("id", 0);
myIntent.putExtras(b);
startActivity(myIntent);
break;
Basically I wanted one class to check which view should be loaded in. So I created a bundle that would be sent through with the intent. That would be check in the activity that is being called.
TextView tv = (TextView) findViewById(R.id.textView1);
Bundle b = getIntent().getExtras();
final long id = b.getLong("id", 0);
if ( id == 0 ) {
setContentView(R.layout.about);
} else if (id == 1) {
tv.setText("THis is number 2");
} else {
tv.setText("Didn't Work");
}
Here is the code on second activity that receives the intent and check to see which view should be loaded it. I don't know if this is the best way of doing it because I have kinda played around a little :)
Would appreciate some feedback on how this could be done better.
Thanks!
P.S. I was wondering if this is a good solution. How would I refactor the intent, just seems like I have to keep copy and pasting the code? How could I create a function to handle this?
Ben Jakuben
Treehouse TeacherOftentimes there is no definitive "best" way in programming, only best practices that serve as guidelines. It is a best practice to associate one Activity with one XML layout file. This keeps things organized as clearly defined pieces of the Model-View-Controller pattern. The layout file is your view. If you load different layout files into the same Activity, then now you'll have one Controller controlling multiple Views. There are some times that's okay, but in general I would try to keep that 1 to 1 ratio.
Now, if your layout files are the same (or at least nearly identical), then maybe it makes sense to load your different content into one Activity with that one layout. Then you could just change the content. I don't know if this fits your example, though. Imagine your menu links to detail Activities that are the same layout but have different titles, descriptions, and images. If the layout can be reused, you could just set the content for each widget in the layout based on whichever row was tapped.
You will end up with some duplicate code like this, but it should be minimal, and there may still be changes to refactor it into common functions.
It's never a bad idea to go ahead with one solution, saving your work at multiple points along the way with git or local backups, and then going back and doing it another way. It's a great way to learn, and you will almost always find ways to improve your original approach no matter what!
If I didn't answer all your questions just repost them in a follow-up reply. :)
Josh Savage
1,817 PointsHi Ben Jakuben,
I sad to say I'm going to have to leave Treehouse.com :( To be honest if I could continue to afford it I would definitely stick you with you guys!
I just wanted to say a really big thank you for all the help and time you've given me. I can happily say I have learn't a lot from you. The way you present your tutorials and the code challenge are very unique and very good!
Thanks once again, maybe one day I hope to return the treehouse :)
All the best in the Future! :)
Josh
Ben Jakuben
Treehouse TeacherJosh Savage - oh no! We're sad to see you go! Keep us in mind so you can come back when it's a good fit for you regarding cost and new content. And I'm glad to hear we've been helpful! :)