Views and Fragments - android-fragments

I have been reading about fragments lately, and almost everyone says that we should use it. I still can't understand the concept very well. I have read this, but I still have some questions.
First: A fragment must be related ( if its the right word) to an activity, let say MainActivity, the fragment has its own layout, the MainActivity has its own two. So what will be displayed on the screen? the fragment layout or the MainActivity or Both??
Second: If I want to convert an existing code to use fragments, what are the main changes?
Third: If I want to have more than one fragment, do I have to add a class that extends Fragment for each fragment I want to create??
Forth: onCreateView of the class that extends Fragment returns a view, is it correct to create a view inside it and return it for the main activity to add it to its layout??
Any help is appreciated.

Here are some tips about fragments what i understand so far , it might help you to understand Fragments :
1: About your first Question, yes both(Activity and Fragment) has their own layouts but Activity layout is act as base layout for fragments but this also depends on the layout you are working. If i state a simple example of HelloWorld app(which automatically created when you first create your Project in eclipse in updated adt), then you saw there Activity act as base and fragment layout show over it.
2: If you want to change the existing code to use fragments,firstly it depends upon the complexity of your code, and after that you have to change various things like if you are supporting api level 10 and below than you have to use Extra Libraries.there are lots of changes to be made but these all depends on your requirements.
3: Yes you have to create a Class which extends Fragment or any other Sub Class of Fragment. This Class is just like your Activity Class in which you have a xml layout to work with.
4: Yes you have to define a view inside OnCreateView() to return it to the activity to add to its layout or to show the UI.
Fragments are just like Activities , the pain comes when you working with Nested Fragments. and the life cycle of fragments are little different than Activity .
Note :please tell me if you have other queries or in case of any doubt about above written statements.

First:
In the layout of MainActivity you can embed multiple fragments layouts. You can even reuse these fragment layouts in any other activity. Ah, Good feature!
Second:
If I want to convert an existing code to use fragments, what are the
main changes?
To use fragments in your existing code you just need to,
The fragments will be added to the activity using the <fragment> element in the layout or can be added dynamically.
To check if the fragment is already part of your layout you can use the FragmentManager class -
DetailFragment fragment = (DetailFragment) getFragmentManager().
findFragmentById(R.id.detail_frag);
if (fragment==null || ! fragment.isInLayout()) {
// start new Activity
}
else {
fragment.update(...);
}
If a fragment is defined in an XML layout file, the android:name attribute points to the corresponding class.
To dynamically add fragments to an existing layout you typically define a container in the XML layout file in which you add a Fragment.
For this you can use, for example, a FrameLayout element.
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.your_placehodler, new YourFragment());
ft.commit();
A new Fragment will replace an existing Fragment that was previously added to the container.
If you want to add the transaction to the backstack of Android, you use the addToBackStack() method.
This will add the action to the history stack of the activity, i.e., this will allow to revert the Fragment changes via the back button.
Third:
If I want to have more than one fragment, do I have to add a class
that extends Fragment for each fragment I want to create??
To define a new fragment you either extend the android.app.Fragment class or one of its subclasses,
for example, ListFragment, DialogFragment, PreferenceFragment or WebViewFragment.
Forth:
onCreateView of the class that extends Fragment returns a view, is it
correct to create a view inside it and return it for the main activity
to add it to its layout??
No need to return it to the main activity to add it to its layout. Just use FragmentTransaction's replace inside Main Activity followed by commit to be done.

Related

Storing a view in Xamarin.Forms MvvmCross

I have an app with four main pages, switched through a tab bar (no "back" button).
One page has a lot of content (ScrollView) and takes quite a few seconds until it's rendered. I handle that by showing a "loading" overlay while the work is done. But for that specific page I'd like to keep the view alive, so that when the user switches to another page and comes back later, the page is ready without loading everything again.
I'm not sure how to do that in MvvmCross, though.
I did read the documentation and from what I understood the View Presenter would be the right way to do it, since the docs say:
"Another kind of presentation changes your app can request through
hints includes clearing / modifying the BackStack, changing a root
while maintaining the existent views, … possibilities are really
endless. Once again your app is king here!"
I guess I would need to create a custom MvxPresentationHint for that, but I don't quite get it :(
How or rather where would I access and store/load the View?
I'm generally still quite unfamiliar with MvvmCross (how it works under the hood) and especially customization of Mvx classes, even though I've been using it for a while.
Any explanation and preferably code examples beyond what's written in the documentation would be extremely appreciated!
It isn't meaningful to attempt to "store" a view in MVVM. The XF view is a representation of what will be created with native (e.g. "Android" or "iOS") widgets. Creating and measuring/laying out those native widgets is what is slow. MVVM View Presenter won't speed up that logic.
Instead of "store", you need "keep alive":
For a ContentPage called MyPage, when you create it, store it in a static variable. Then re-use that variable. If you never need more than one of these, you can store it in the class itself.
Modify the "code behind", MyPage.xaml.cs:
public partial class MyPage : ContentPage
{
// Singleton Pattern.
private static MyPage _it;
public static MyPage It {
get {
if (_it == null)
_it = new MyPage();
return _it;
}
}
// "private", because calling this directly defeats the purpose. Instead, use `MyPage.It`.
private MyPage()
{
InitializeComponent();
}
}
To create it, whereever you would put:
new MyPage()
instead put this:
MyPage.It
For instance, you might do PushAsync(MyPage.It);
This will always return the SAME INSTANCE of MyPage. So once it has been created, it keeps its state.
IMPORTANT: Note that the constructor is only called ONCE. Any code that needs to be done each time the page appears, put in override .. OnAppearing() method.
LIMITATION: Views "expect" to be part of the visual hierarchy when they are manipulated. If you attempt to alter the page or its view model while it is not on the screen, you may encounter problems. Those are beyond the scope of this answer - create a new StackOverflow question with the details of any problem you encounter.

How to implement transition between two PageRow in leanback BrowseFragment?

I'm using a leanback BrowseFragment to implement a simple android tv app. I have two PageRows which are backed by custom fragments. When I switch between the two in the browse navigation area, the content side of the screen goes blank briefly before the new fragment's views appear. How can I fade from one view to the other without a delay in between?
I see some references to "entrance transition" in the docs which I think is what I need, but I can't find any examples of what to do in those callbacks.
https://developer.android.com/reference/android/support/v17/leanback/app/BrowseFragment.MainFragmentAdapter.html#setEntranceTransitionState(boolean)
I tried to implement setEntranceTransitionState on my PageRow Fragment's MainFragmentAdapter, but it is never invoked:
class GuideFragment: Fragment(), BrowseFragment.MainFragmentAdapterProvider {
val fragmentAdapter = object: BrowseFragment.MainFragmentAdapter<GuideFragment>(this) {
override fun setEntranceTransitionState(state: Boolean) {
Log.v("TEST", "setEntrance($state)")
fragment.setEntranceTransitionState(state)
}
}
override fun getMainFragmentAdapter() = fragmentAdapter
}
There is no way to do this when using BrowseSupportFragment.
If you look at the implementation of swapToMainFragment(), you'll see that while scrolling the content is set to an empty fragment. When SCROLL_STATE_IDLE is reached, a regular fragment transaction is used to replace the child fragment with the new content.
leanback has a lot of limitations, It is better to fork the official code and create your own repo and modify it; we did the same in our app.

[Flex mobile]About placing many instances of a custom component

Right now , my development of app is in the optimizing stage. I have a problem when adding one of my components: PlayerInfo, which is extended from Group and has some Labels and Images in it,I have to create 60 of this component and put'm all into a HGroup. But in the process of adding them into the hgroup, my app just stops responding for a few seconds,which is not tolerable. Can I achieve this with less memory usage?
I have read this page and thought if I can do it with any of my components,not only bitmaps.does anyone know how to do that?
here is how I did it:
class PlayerInfo extends Group{
private var name:Label;
private var age:Label;
private var photo:Image;
}
and in my list class:
public function addPlayers(arrPlayer:Array):void{
for(;;){
var player:PlayerInfo=new PlayerInfo();
HGroup.addElement(player);
}
}
Can I achieve this with less memory usage?
Yes! With your current approach; if you have 60 instances of your component, then the app creates 60 instances of the component, renders them all and puts them on the screen; even if they are not currently a view area.
You should make use of a class, such as a List or DataGroup, as #RiaStar suggests. Your custom component, PlayerInfo, should be used as the itemRenderer and the 'list' you are creating these components from should become the List's dataProvider.
Once you do this, then your app will make use of the List's renderer recycling. So, only the visual elements displayed on screen will be displayed to the user. So, if you have 10 items shown on screen from your list of 60; the app will generate 50 less an items. This will make better use of processing power and better use of device memory.
To change your class to a renderer, you will have to implement a dataChange() event handler so that the component updates whenever the list changes the data that the renderer should display.
I don't think we enough information to get a more detailed explanation. What is your dataProvider? What propeties need to be set on your custom component?

Can you have a loader without fragments

Very basic loader question.
My WIMMOne watch uses Android 2.1 (version 7).
There are no orientation changes, etc. with a watch. The small screen does not have room for any layout changes. So no need to deal with any kind of layout change.
The app I am working on now simply reads from a cursor, and displays an open ended scrolling list. My first app had a fragment and that was a pain. So I decided since I don't need fragments I will do away with the complexities of fragments.
I START WITH:
public class PhoneListActivity extends Activity
implements LoaderManager.LoaderCallbacks <Cursor>;
THEN:
protected void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState);
setContentView(R.layout.phone_list_activity);
FINALLY:
getLoaderManager().initLoader(0, null, this);
BUT:
Because it is 2.1 I need to use:
getSupportLoaderManager().initLoader(0, null, this);
BUT: -
That generates compile errors, so I need to use:
public class PhoneListActivity extends FragmentActivity . . . (not just Activity)
BUT: -
It immediately crashes on load in the ContentProvider.
Postings in various sites refer to "Activities and ActivityFragments".
SO: QUESTION 1: Can my main class use "extends FragmentActivity" without setting up a separate fragment (ie: leave it just as an Activity).
QUESTION 2: If not, does that mean that to use a loader I must set up a separate fragment and deal with the issues of fragments?
Many thanks,
Clark
The answer is YES.
I redid part of the program and it now works without using fragments. It has the open ended scrolling being loaded from a cursor and basically the same structure above
I think something in handling my cursor was causing it to crash.
Clark

Flex and fake Mxml initialisation without actually showing the component, (more insise)

I have a TitleWindow mxml class wich has several components, and listeners.
On its creationComplete and init state i add some listeners which listen for events on its gui.
This TitleWindow is only shown when the user click on a "button", i made TitleWindow a singleton with the following code:
public static function getInstance():MyWindow
{
if ( MyWindow.singleton )
{
return MyWindow.singleton;
}
else{
MyWindow.singleton = new MyWindow();
return MyWindow.singleton;
}
}
I needed a singleton because the user will call this window several times as much as he wants and i only need one.
The problem is the following on some special external events i need to "modify" some listeners (remove listeners and add new ones) on a button from MyWindow, before it was even shown once.
I still have MyWindow.getInstance() in memory when my application starts up.
However adding /removing listeners does not seem to have any effect if he actual rendering of the components did not happen, event when using the following code on app startup.
myWindow= MyWindow.getInstance();
myWindow.initialize();
Not suprisingly if i "show" ('render') the myWindow at least once then the events modifications on the myWindow instance works perfectly.
How can i fake the complete initialisation of this component without showing it on startup ?
Thanks !
Which sort of a container holds your button? If you are using a Multiple View Container you can try setting the creationPolicy to all. Single View Containers create all their children in one go and you shouldn't face this problem.
From Flex 3.0 docs I could retrieve this:
The default creation policy for all containers, except the Application container, is the policy of the parent container. The default policy for the Application container is auto.
This looks like the cause for all your troubles.
Update: I did not mention this earlier, since I thought this was to be expected :) Setting the creationPolicy to all makes your application load more slowly. So, read up on Ordered Creation -- this technique helps you to choose if the controls are displayed all in one go (which is the default behavior, after all of the controls have been created) or step-by-step, as and when they are created.

Resources