Pages

mardi 28 mai 2013

Android FRAGMENT SWAPPING

This android tutorial shows how to swap two fragments. The goal was to re-use the fragment instances when rotating, no new fragment instances are re-created when rotating. There is also two layouts : one for portrait mode and one for landscape mode. In portrait mode, the second panel is below the first panel. In landscape mode, the second panel is on the right of the first panel. The support android library has been used.





InitialAfter Swap
Portraitfragswapping02fragswapping01
Landscapefragswapping04fragswapping03

Layout for portrait mode :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical"
   android:baselineAligned="false">
    <FrameLayout
        android:id="@+id/container1"
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        android:layout_weight="1">
    </FrameLayout>
    <FrameLayout
        android:id="@+id/container2"
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        android:layout_weight="1">
    </FrameLayout>
</LinearLayout>
Layout for landscape mode :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="horizontal"
   android:baselineAligned="false">
    <FrameLayout
        android:id="@+id/container1"
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        android:layout_weight="1">
    </FrameLayout>
    <FrameLayout
        android:id="@+id/container2"
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        android:layout_weight="1">
    </FrameLayout>
</LinearLayout>
FragmentSwappingActivity : in the activity we try to find the fragment instances in each container. If the fragment is not found, it is instantiated and loaded inside the container.
package org.michenux.fragswapping;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;

public class FragmentSwappingActivity extends FragmentActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        FragmentManager fm = getSupportFragmentManager();
        Fragment frag1 = fm.findFragmentById(R.id.container1);
        if ( frag1 == null ) {
            frag1 = Panel1Fragment.newInstance();
            FragmentHelper.initFragment( frag1, R.id.container1, fm);
        }
        
        Fragment frag2 = fm.findFragmentById(R.id.container2);
        if ( frag2 == null ) {
            frag2 = Panel2Fragment.newInstance();
            FragmentHelper.initFragment( frag2, R.id.container2, fm);
        }
    }
}
The FragmentHelper class :
package org.michenux.fragswapping;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;

public class FragmentHelper {

    public static void initFragment( Fragment frag, int container, FragmentManager fm ) {
        FragmentTransaction ft = fm.beginTransaction();
        ft.add(container, frag);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();        
    }
    
    public static void swapFragment( int container1, int container2, FragmentManager fm ) {
        
        Fragment f1 = fm.findFragmentById(container1);
        Fragment f2 = fm.findFragmentById(container2);

        FragmentTransaction ft = fm.beginTransaction();
        ft.remove(f1);
        ft.remove(f2);
        ft.commit();
        fm.executePendingTransactions();
            
        ft = fm.beginTransaction();
        ft.add(container1, f2);
        ft.add(container2, f1);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
            
        ft.commit();
    }
}
The Panel1Fragment class: Nothing interesting in this class except the call to the swap.
package org.michenux.fragswapping;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

public class Panel1Fragment extends Fragment {

    private static int countInstance = 1 ;
    
    public static Panel1Fragment newInstance() {
        Panel1Fragment frag = new Panel1Fragment();
        Bundle args = new Bundle();
        args.putInt("instanceNumber", countInstance);
        frag.setArguments(args);
        countInstance++ ;
        return frag;
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
                
        View mainView = inflater.inflate(R.layout.panel1, container, false);

        int instanceNumber = getArguments().getInt("instanceNumber");
        TextView txtView = (TextView) mainView.findViewById(R.id.panel1Number);
        txtView.setText("instance number: "+instanceNumber);
    
        Button oButton = (Button) mainView.findViewById(R.id.button1);
        oButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                FragmentHelper.swapFragment(R.id.container1, R.id.container2, getFragmentManager());
            }

        });
        return mainView;
    }
}
Layout for Panel1Fragment.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >

    <TextView
       android:id="@+id/panel1Text"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Panel1" />
    
     <TextView
       android:id="@+id/panel1Number"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="0" />

    <Button
       android:id="@+id/button1"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Swap" >
    </Button>

</LinearLayout>
I don’t post the Panel2Fragment source code. It is quite identical to the Panel1Fragment except it has no button.
In a future post, i will show how to do a master-detail view with fragments with the same constraint: re-using fragment instances.

0 commentaires:

Enregistrer un commentaire