Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Fragments: Why? How? and What For?

42df4bd18a5688739a6aa58a04cce043?s=47 Brenda Cook
January 20, 2016

Fragments: Why? How? and What For?

42df4bd18a5688739a6aa58a04cce043?s=128

Brenda Cook

January 20, 2016
Tweet

More Decks by Brenda Cook

Other Decks in Programming

Transcript

  1. Fragments Why? How? What for?

  2. Who Needs Fragments?

  3. Who Needs Fragments? You do!

  4. Why?

  5. • Smaller View Controllers

  6. • Smaller View Controllers • Reusable UI & Logic Components

  7. • Smaller View Controllers • Reusable UI & Logic Components

    • Address device fragmentation
  8. • Smaller View Controllers • Reusable UI & Logic Components

    • Address device fragmentation • Decomposition of application code
  9. How do they work?

  10. Image Credit: Steve Pomeroy | github.com/xxv/android-lifecycle

  11. Image Credit: Lars Vogel | vogella.com

  12. onViewCreated() onViewStateRestored()

  13. Static vs Dynamic

  14. Adding Fragments Statically <fragment xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/puppy_list"
 android:name="com.kenodoggy.masterdetailflow.PuppyListFragment"
 android:layout_width="match_parent"
 android:layout_height="match_parent"


    android:layout_marginLeft="16dp"
 android:layout_marginRight="16dp"
 tools:context=".PuppyListActivity"
 tools:layout="@android:layout/list_content"/>
  15. Dynamically Adding Fragments Instantiation Rules you must know

  16. public MyFragment() {
 // Required empty public constructor
 } Default

    Constructor
  17. public static MyFragment newInstance(int position) {
 MyFragment fragment = new

    MyFragment();
 Bundle args = new Bundle();
 args.putInt(ARG_POSITION, position);
 fragment.setArguments(args);
 return fragment;
 } New Instances
  18. public static MyFragment newInstance(int position) {
 MyFragment fragment = new

    MyFragment();
 Bundle args = new Bundle();
 args.putInt(KEY_POSITION, position);
 fragment.setArguments(args);
 return fragment;
 } New Instances
  19. Adding a Fragment MyFragment fragment = MyFragment.newInstance(args);
 
 getFragmentManager().beginTransaction()
 .add(R.id.fragment_container,

    fragment)
 .commit();
  20. Adding a Fragment MyFragment fragment = MyFragment.newInstance(args);
 
 getFragmentManager().beginTransaction()
 .add(R.id.fragment_container,

    fragment)
 .commit();
  21. Replacing a Fragment MyFragment fragment = MyFragment.newInstance(args);
 
 getFragmentManager().beginTransaction()
 .replace(R.id.fragment_container,

    fragment)
 .commit();
  22. None
  23. Destruction

  24. Image Credit: Lars Vogel | vogella.com onSaveInstanceState()

  25. setRetainInstance(true) @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 
 //

    Retain this fragment across configuration changes.
 setRetainInstance(true);
 }
  26. Examples

  27. Dual / Single Pane Design aka Master / Detail

  28. None
  29. Specifying Layouts Based on Screen Properties

  30. Navigation Layout for Phone <fragment xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/puppy_list"
 android:name="com.kenodoggy.masterdetailflow.PuppyListFragment"
 android:layout_width="match_parent"


    android:layout_height="match_parent"
 android:layout_marginLeft="16dp"
 android:layout_marginRight="16dp"
 tools:context=".PuppyListActivity"
 tools:layout="@android:layout/list_content"/>
  31. Detail Layout for Phone <android.support.design.widget.CoordinatorLayout>
 <android.support.design.widget.AppBarLayout>
 <android.support.design.widget.CollapsingToolbarLayout>
 <android.support.v7.widget.Toolbar />
 </android.support.design.widget.CollapsingToolbarLayout>


    </android.support.design.widget.AppBarLayout> 
 <android.support.v4.widget.NestedScrollView
 android:id="@+id/puppy_detail_container"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 app:layout_behavior=“@string/appbar_scrolling_view_behavior"/> 
 </android.support.design.widget.CoordinatorLayout>

  32. None
  33. List/Detail Layout for Tablet <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:orientation="horizontal">
 
 <fragment


    android:id="@+id/puppy_list"
 android:name="com.kenodoggy.masterdetailflow.PuppyListFragment"
 android:layout_width="0dp"
 android:layout_height="match_parent"
 android:layout_weight="1"
 tools:layout="@android:layout/list_content"/>
 
 <FrameLayout
 android:id="@+id/puppy_detail_container"
 android:layout_width="0dp"
 android:layout_height="match_parent"
 android:layout_weight="3"/>
 
 </LinearLayout>
  34. Determining Which Layout to Display

  35. None
  36. None
  37. None
  38. None
  39. Dual or Single Pane? if (findViewById(R.id.puppy_detail_container) != null) {
 //

    The detail container view will be present only in the
 // large-screen layouts (res/values-large and
 // res/values-sw600dp). If this view is present, then the
 // activity should be in two-pane mode.
 mTwoPane = true;
 
 ... code specific to two pane layout
 }
  40. Tabbed ViewPager Using TabLayout

  41. None
  42. The Parent Activity Layout <android.support.design.widget.CoordinatorLayout>
 <android.support.design.widget.AppBarLayout>
 <android.support.v7.widget.Toolbar />
 
 <android.support.design.widget.TabLayout

    android:id="@+id/tabs"
 android:layout_width=“wrap_content" android:layout_height="wrap_content"
 app:tabMode="scrollable"/>
 
 </android.support.design.widget.AppBarLayout>
 
 <android.support.v4.view.ViewPager android:id="@+id/container"
 android:layout_width="match_parent" android:layout_height="match_parent"
 app:layout_behavior="@string/appbar_scrolling_view_behavior" />
 
 </android.support.design.widget.CoordinatorLayout>
  43. The Parent Activity Layout <android.support.design.widget.CoordinatorLayout>
 <android.support.design.widget.AppBarLayout>
 <android.support.v7.widget.Toolbar />
 
 <android.support.design.widget.TabLayout

    android:id="@+id/tabs"
 android:layout_width=“wrap_content" android:layout_height="wrap_content"
 app:tabMode="scrollable"/>
 
 </android.support.design.widget.AppBarLayout>
 
 <android.support.v4.view.ViewPager android:id="@+id/container"
 android:layout_width="match_parent" android:layout_height="match_parent"
 app:layout_behavior="@string/appbar_scrolling_view_behavior" />
 
 </android.support.design.widget.CoordinatorLayout>
  44. Setting up our ViewPager 
 ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());


    
 /* add the Fragments to the ViewPagerAdapter */
 for(String title : mPuppyTitles) {
 adapter.addFrag(PuppyFragment.newInstance(index++), title);
 }
 
 mViewPager.setAdapter(adapter);
  45. Creating our PuppyFragment @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);


    if (getArguments() != null) {
 mPageNumber = getArguments().getInt(ARG_POSITION);
 }
 }
  46. Loading the UI @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,


    Bundle savedInstanceState) {
 View view = inflater.inflate(R.layout.fragment_puppy, container, false);
 
 int imageId = getResources().getIdentifier(mPuppyImages[mPageNumber],
 "drawable", getActivity().getPackageName()); 
 ImageView image = (ImageView) view.findViewById(R.id.puppy_picture);
 image.setImageResource(imageId);
 
 return view;
 }
  47. Loading the UI @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,


    Bundle savedInstanceState) {
 View view = inflater.inflate(R.layout.fragment_puppy, container, false);
 
 int imageId = getResources().getIdentifier(mPuppyImages[mPageNumber],
 "drawable", getActivity().getPackageName()); 
 ImageView image = (ImageView) view.findViewById(R.id.puppy_picture);
 image.setImageResource(imageId);
 
 return view;
 }
  48. Navigation Drawer

  49. None
  50. None
  51. Fragment fragment = DetailFragment.newInstance(puppy, position);
 
 FragmentManager fragmentManager = getFragmentManager();


    FragmentTransaction transaction = fragmentManager.beginTransaction();
 // do replace and commit operation
 transaction.replace(R.id.detail_container, fragment).commit();
  52. Fragment fragment = DetailFragment.newInstance(puppy, position);
 
 FragmentManager fragmentManager = getFragmentManager();


    FragmentTransaction transaction = fragmentManager.beginTransaction();
 // do replace, add to backstack and commit operation
 transaction.replace(R.id.detail_container, fragment) .addToBackStack(“details”) // optional name for this back stack state, or null .commit();
  53. Going Back • Fragment: popBackStack() • Activity: onBackPressed()

  54. DialogFragment

  55. Constructing a DialogFragment Two ways:

  56. Constructing a DialogFragment Two ways: @Override onCreateView()

  57. Constructing a DialogFragment Two ways: @Override onCreateDialog() @Override onCreateView()

  58. public class SampleDialogFragment extends DialogFragment implements DialogInterface.OnClickListener {
 @Override
 public

    Dialog onCreateDialog(Bundle savedInstanceState) {
 View view = getActivity() .getLayoutInflater() .inflate(R.layout.fragment_sample_dialog, null);
 
 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
 
 return(builder
 .setView(view)
 .setTitle(title)
 .setPositiveButton(R.string.close, null)
 .create());
 }
 }
  59. public class SampleDialogFragment extends DialogFragment implements DialogInterface.OnClickListener {
 @Override
 public

    Dialog onCreateDialog(Bundle savedInstanceState) {
 View view = getActivity() .getLayoutInflater() .inflate(R.layout.fragment_sample_dialog, null);
 
 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
 
 return(builder
 .setView(view)
 .setTitle(title)
 .setPositiveButton(R.string.close, null)
 .create());
 }
 }
  60. public class SampleDialogFragment extends DialogFragment implements DialogInterface.OnClickListener {
 @Override
 public

    Dialog onCreateDialog(Bundle savedInstanceState) {
 View view = getActivity() .getLayoutInflater() .inflate(R.layout.fragment_sample_dialog, null);
 
 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
 
 return(builder
 .setView(view)
 .setCustomTitle(title)
 .setPositiveButton(R.string.close, null)
 .create());
 }
 }
  61. Showing your DialogFragment SampleDialogFragment frag = SampleDialogFragment.newInstance(args); frag.show(getFragmentManager(), SampleDialogFragment.TAG);

  62. 
 return(builder
 .setTitle(title) .setMessage(“Dialog Message”)
 .setPositiveButton(R.string.close, null)
 .create());


  63. None
  64. Dismissing a DialogFragment

  65. Communicating with the Parent Activity

  66. Define an Interface public interface OnDialogDismissed {
 void onDialogDismissed(String whichSalutation);


    }
  67. @Override
 public void onAttach(Activity activity) {
 super.onAttach(activity);
 try {
 mDialogDismissedCallback

    = (OnDialogDismissed)activity;
 } catch (ClassCastException cce) {
 Log.e("Error", getClass().getSimpleName() + ", calling Activity must implement OnDialogDismissed");
 }
 }
  68. public class MainActivity extends AppCompatActivity implements SampleDialogFragment.OnDialogDismissed {
 // ...

    other methods and implementation not shown
 @Override
 public void onDialogDismissed(String whichSalutation) {
 if (whichSalutation.equals(SampleDialogFragment.GOODBYE)) {
 Toast.makeText(this, "Thank you!", Toast.LENGTH_SHORT).show();
 }
 }
 }
  69. @Override
 public void onClick(DialogInterface dialog, int which) {
 // display

    a toast when the dialog is dismissed for GOODBYE only
 if (mSalutation.equals(GOODBYE)) {
 mDialogDismissedCallback.onDialogDismissed(GOODBYE);
 }
 }
  70. None
  71. Thank you Source Code: github.com/kenodoggy/ Slides: speakerdeck.com/kenodoggy/ Twitter @kenodoggy g+

    +BrendaCook_kenodoggy