I have read some examples, tutorials, question on stackoverflow, but till now I don't think
it's quite clear if what I want to do should be simpler or done anyway!
I will post a draft design for better understanding.
As you can see I just need to have a fragment like the above which will inflated by an Activity and this fragment should contain some custom compound controls and other simple Views.
Now I need as you can see on the left of the draft a Tab (control) which will simply contain Views into each tab area and interact with them through the fragment.
I think its so redundant using different activity for every tab or even different fragment.
I thought of a solution with buttons and visible/hide views.
Any examples, tutorials solving such a problem welcome.
Thank you.
You can just create buttons in place of tabs and you can just change the
setContentView(yourlayout)
accordingly Example
public void onClick(View v) {
switch (v.getId()) {
case R.id.tab1:
setContentView(R.layout.tab1);
// perform other changes if needed
break;
case R.id.tab2:
setContentView(R.layout.tab2);
break;
case R.id.tab3:
setContentView(R.layout.tab3);
break;
}
this will be useful if you have minimum level of functionality to perform
There are several ways of achieving this. You could use ViewPager + ViewPagerIndicator. Or display the content as separate Fragments in a FrameLayout, and replace it with FragmentTransaction's when user selects a different tab. One bonus with the ViewPager implementation is that the user can swipe between the different tabs.
Related
I am a newbie in Android. I want to ask that do I need to create an activity class for each page in my app? If not what can I do to bring new pages on screen? Is layout inflater a good choice for this?
Thank you.
Lets say, I have a list view which contains questions. When you click one of them you will see the answer o another page. This means lots of activity class. Then I am looking for another solution.
No, you don't need different activities for this. You can make your "Answer activity" dynamic. It can change data according to which ListView item was clicked. Here's a simple solution to your problem. Create a new int variable and change it accordingly to which ListView item was clicked. If item at index 0 was clicked, then this int should be 0. Pass it with extras to your answer activity and in your answer activity, implement an IF statement.
if (intVariable == 0)
{
//show answer 0
}
else if (intVariable == 1)
{
//show answer 1
}
Do you get the concept?
So, if you want to change the layout accordingly to which ListView item was clicked, this might help you.
Are you changing only image sources or actual layout positions? If you're changing positions, you might aswell create another activity because changing layout positions programatically would take too much time and it's too complicated.
Do you only want image sources to change but layout positions to stay the same? Then this is easier. This code might help you:
int position = //get int extras here
switch (position)
case 0:
imageView1.setImageResources(r.id.yourPicture);
case 1:
imageView1.setImageResources(r.id.yourPic2);
So as you can see, your image resource changed accordingly to ListView item clicked.
Yes, to use activities is the most common way to display content. You can bring new content, that is new activities on the screen by starting new activities via Intent. Therefore, make sure to check out the activity lifecycle
http://developer.android.com/training/basics/activity-lifecycle/index.html.
On the other hand, it sometimes is useful to use fragments to display content on the screen. Fragments are basically "multiple screens" that are hosted by one parent activity. By using fragments you can achieve views like the one in the Skype android app.
Here is more on fragments: http://developer.android.com/training/basics/fragments/index.html
All in all: Use activities to display static content and fragments to make your views more dynamic.
Not necessary, it depends on your design. A typical example is Android Gallery, which is implemented in OpenGL. All pages of Gallery are in one Activity. The advantage is the switching speed is fast, and UI seems much slick. Starting a new Activity may cost much and cause delay. So how to implement it this? You need to create a stack for storing all pages, and manually control(add or remove) them while switching different pages. Anyway, it depends on how you want to design your app(some pages could be displayed in new Activity, some pages not). You have to consider cost and performance.
I am using new activities for ActivityButtons. So I have like 10 different activities, all of them using the same footer. In the footer, there are buttons and lots of click events. I just copy pasted all the listener events for Footer buttons to a few other activities to test it. It works but I need to find a way to keep them all together somewhere so that I will modify only once when I need to.
I tried keeping all common methods in a separate utility class by making them static, however it has a limited use. I am having issues with references and non-static methods.
In my research I have read about the ViewFlipper. Would it be better if I used a single MainActivity for everything and a ViewFlipper to switch between layouts. I have read that this might cause some resource issues, since the one and only activity will be active all the time.
Do you have any suggestions for this problem?
Thanks in advance.
There are a few things to consider.
Fist is that footers are a somewhat problematic design pattern on android. Because of devices with soft buttons right below the screen area it is very easy for users to accidentally click system buttons when they are aiming for footer, and vice versa. If you are dead set on using a footer I suggest that you leave ample margin between it and the bottom edge of the screen to help mitigate this.
You have a few options for how to handle the layout and click listeners. You could make the footer into its own Fragment And simply add it to each Activity that needs it. This is arguably the more difficult approach, but it would provide a good learning experience with Fragments if you are up for the challenge.
Another option is to but all of your footer click listeners inside their own activity and then extend that with all of your other activities. Something like this:
public class FooterActivity extends Activity{
Button btn1
//...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.id.yourLayout);
btn1 = (Button)findViewById(R.id.btn1);
btn1.setOnClickListener(yourClickListener);
//...
}
}
Then in your normal activities change extends Activity to extends FooterActivity
You can create a ParentActivity, which will handle onClick method, and then let your other Activities to extend that ParentActivity to do what is specific for them.
The other approach would be to use Fragments. Create one fragment that will handle the Footer, and other would be different based on work they are expected to work.
TL;DR:
How should multi-pane apps with deep navigation similar to the Spotify iPad app look and work on Android, and how to implement this?
Long version:
I'm working on an app, where the user sees lists of items and can then delve deeper into these items. These item detail pages can again open lists of related items, that in turn have detail pages and so on. As a phone app, these would be separate Activities that might look and link to each other like this:
In the mock-ups, the user sees an initial overview and then selects "Item #2" from the first list. A new Activity opens up, showing him details for Item #2. Here, he selects to see a list of Things relating to Item #2. The newly openend Activity in the third picture shows this list, and clicking on one opens the details for this thing. He can navigate as deep into the content as he likes.
This works quite well with the usual Android Activities. I'm working on bringing the app to tablets and am thinking on how to best implement this. The plan is to create a multi-pane layout with the same concept. It is very similar to how the iPad Spotify app works (it will be interesting to see how they bring this to Android once they create tablet-specific layouts).
In the tablet layout, each click on an item or list name opens the corresponding child item as a new pane that animates in from the right. The same workflow as in the example above would look like this:
I'm unsure how to best implement this navigation pattern. Multi-pane apps with a limited navigational depth like GMail can be built with a static ViewGroup (LinearLayout would be ok) containing all fragments, and going deeper into the navigation replaces the content of the next container to the right and animates to this (see CommonWares implementation of this on SO).
This suggests that a custom ViewGroup would be the way to go. If it has to display a subpage (i.e. "List of Things"), then it creates a new child in the ViewGroup that is half as wide the screen with the fragment and then scrolls the visible area so that the pane that was just interacted with and the new child are visible. To link this correctly to a FragmentTransaction, so that the back stack works correctly, I'd guess it would be something like this:
View newPane = container.addChild();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(newPane, new ListOfThingsFragment(2));
ft.remove(paneOnRight, fragmentOnRight);
ft.commit();
container.animateToRight();
I don't see a way to do the animation within the FragmentTransaction.
Feedback welcome. My employer is generally favorable with respect to open sourcing frameworks we develop, so if this is something that is of broader interest and if I can come up with a reusable solution, I'd be glad to share it.
I had some research time and came up with a solution to this question (a question that I've wanted to see the solution for LONG time, even before you asked it).
I can't really show the whole code as there's some IP boundaries, but I'll put it here the main parts for this animation to works.
There're two key tools: setCustomAnimations and LayoutTransition
Yes, as far as I've been able to do it, you need to separate set animations to make it work.
So let's get to some code, you'll define your XML with a horizontal LinearLayout and make sure to include the following line on it.
android:animateLayoutChanges="true"
this will auto-generate a standard LayoutTransition which does translate the fragment/view that is staying in the layout and alpha (in or out) the fragment/view that is being included or removed from the layout. Give it a try.
So after this layout is inflated we gonna capture this LayoutTransition and trick it out to our needs:
LayoutTransition lt = myLinearLayout.getLayoutTransition();
lt.setAnimator(LayoutTransition.APPEARING, null);
lt.setAnimator(LayoutTransition.DISAPPEARING, null);
lt.setStartDelay(LayoutTransition.CHANGE_APPEARING, 0);
lt.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
with that code, we're removing the alpha animations and removing any delay from the transition (because we want all the translations to fire together).
And now it's just a few simple fragment transactions to make it work, during initialisation we inflate that layout and put a few fragments on it:
setContentView(R.layout.main); // the layout with that Linear Layout
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.main, frag1, FRAG_1_TAG); // it's good to have tags so you can find them later
ft.add(R.id.main, frag2, FRAG_2_TAG);
ft.add(R.id.main, frag3, FRAG_3_TAG);
ft.hide(frag3);
ft.commit();
now on the transaction it's a simple:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out, R.anim.push_right_in, R.anim.push_right_out);
Fragment left = getFragmentManager().findFragmentByTag(FRAG_1_TAG);
Fragment right = getFragmentManager().findFragmentByTag(FRAG_3_TAG);
ft.hide(left);
ft.show(right);
ft.addToBackStack(null);
ft.commit();
final notes:
to make deeper navigation it's just a matter of firing FragmentTransactions to add fragments to the LinearLayout and hide or detach the left side fragment.
Also to make the fragments work on the linear layout is important to set their LinearLayout.LayoutParams.weight during runtime, something similar to the following code applied to the fragment view
((LinearLayout.LayoutParams) view.getLayoutParams()).weight = 1;
to make it work on phones as well it's just a matter of applying the common multiple screen support patterns.
last note, be careful on proper managing the layout status during device rotation because it's not all automagically handled by the system.
Happy coding!
We ran into the same problem with our app. The constraints we gave ourselves:
Dynamic numbers of panes
Each pane can be differently sized
Fragments inside of panes must be correctly retained on orientation changes.
In light of those constraints, we built a new layout we call PanesLayout. You can check it out here:
https://github.com/cricklet/Android-PanesLibrary
It basically allows you to easily add any number of dynamically sized panes and attach fragments to those panes. Hope you find it useful! :)
Partial answer to the animation part:
You can do animations with the FragmentTransaction:
ft.setCustomAnimations(android.R.anim.slide_in_left,
android.R.anim.slide_out_right);
Update: see this answer from Reto Meier himself about fragment animation: https://stackoverflow.com/a/4819665/1007169
How do you switch between layouts in an activity and populate fields based on layout currently used?
For example if there is a logic in a view to load a view:
if(category == 1){
setContentView(R.layout.layout1);
}else{
setContentView(R.layout.layout2);
TextView title = (TextView) findViewById(R.id.titleTV);
title.setText("myTitle");
}
If the else code is called the view never sets the title TextView to the String.
How do I accomplish conditionally going between the two views?
Another alternative would be to use Fragment. The advantage over the choices dimitris mentioned is that each fragment has it's own lifecycle, so you can delegate all code related to each view to its fragment, and keep your main activity clean.
To do this, simply use a FrameLayout in the Activity as a placeholder for the fragments. Fragments can communicate with the activity by using the listener pattern.
In case you want to flip across difference Views you can examine various possibilities, such as:
ViewPager via the compatibility library (http://android-developers.blogspot.com/2011/08/horizontal-view-swiping-with-viewpager.html)
ViewFlipper or ViewSwitcher (http://developer.android.com/reference/android/widget/ViewFlipper.html, http://developer.android.com/reference/android/widget/ViewSwitcher.html)
Or even a simple FrameLayout (http://developer.android.com/reference/android/widget/FrameLayout.html)
Hope this helps for now! In case you need anything specific please shoot it!
BTW have you considered Fragments. They are meant to deal with conditional layouts. Their basic motivation is screen sizes etc. But they can also fit your problem.
Refer to:
Fragments
I have a group of tabs. In one of the tabs, I want to display two different types of functionality.
So my question is it better to implement a activity group with child activities or just create a view flipper and switch between views.
ActivityGroup is used to manage one or more activity example. if two different activity have different implementation but the user want to see on sharing screen basis means in first half user want to see some thing and in second have some other thing. In that case ActivityGroup comes to play
ViewFlipper can be used if you want to periodically change the views. Say like an automated flipping book of some sort. Though a custom-adapter gallery is much better at this.
Both have different purpose. It depends on your requirement you will choose any of them.
i would go with a view flipper. you probably dont need the whole overhead of creating another activity. but that way will make your single activity that will hold them a bit larger. so also maybe try to implement some of the functionality inside the views you will be adding.
hope this helps.