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

Tools & tips of the trade for the Android Developer

Saul Molinero
September 18, 2015

Tools & tips of the trade for the Android Developer

Slides of the keynote given at the Spanish GDG summit on September 2015

Saul Molinero

September 18, 2015
Tweet

More Decks by Saul Molinero

Other Decks in Programming

Transcript

  1. Tools & tips of the trade for the Android Developer

    Saúl Molinero Spanish GDGs Summit 2015
  2. <android.support.design.widget.CoordinatorLayout>   <android.support.design.widget.AppBarLayout   android:id=“@+id/io.appbar”/>   
 <!—-­‐  Appbar  childs

     —-­‐>   </android.support.design.widget.AppBarLayout/>   <android.support.v4.widget.NestedScrollView>        <TextView/>   </android.support.v4.widget.NestedScrollView>
  <android.support.v7.widget.Toolbar        app:layout_anchor=“@id/io.appbar”        app:anchor_gravity=“bottom”  >                  <!—-­‐  Toolbar  childs  —-­‐>   </android.support.v7.widget.Toolbar>   <android.support.design.widget.CoordinatorLayout/>   Coordinator Layout: Anchor attributes
  3. <android.support.design.widget.CoordinatorLayout>   <android.support.design.widget.AppBarLayout/>   <android.support.v4.widget.NestedScrollView    android:behavior_overlapTop=“78dp”>      

     <TextView/>   </android.support.v4.widget.NestedScrollView>   <android.support.design.widget.CoordinatorLayout/>   CoordinatorLayout: Flexible Space https://github.com/saulmm/CoordinatorExamples
  4. 
 public static class AvatarImageBehavior extends 
 CoordinatorLayout.Behavior<CircleImageView> { @Override

    public boolean layoutDependsOn(
 CoordinatorLayout parent, CircleImageView, child, View dependency) { return dependency instanceof Toolbar; }
 
 public boolean onDependentViewChanged(
 CoordinatorLayout parent, CircleImageView avatar, View dependency) {
 modifyAvatarDependingDependencyState(avatar, dependency); } }
  5. 
 public static class AvatarImageBehavior extends 
 CoordinatorLayout.Behavior<CircleImageView> { @Override

    public boolean layoutDependsOn(
 CoordinatorLayout parent, CircleImageView, child, View dependency) { return dependency instanceof Toolbar; } 
 
 public boolean onDependentViewChanged(
 CoordinatorLayout parent, CircleImageView avatar, View dependency) {
 modifyAvatarDependingDependencyState(avatar, dependency); } }
  6. 
 public static class AvatarImageBehavior extends 
 CoordinatorLayout.Behavior<CircleImageView> { @Override

    public boolean layoutDependsOn(
 CoordinatorLayout parent, CircleImageView, child, View dependency) { return dependency instanceof Toolbar; } 
 
 public boolean onDependentViewChanged(
 CoordinatorLayout parent, CircleImageView avatar, View dependency) {
 modifyAvatarDependingDependencyState(avatar, dependency); } }
  7. 
 public static class AvatarImageBehavior extends 
 CoordinatorLayout.Behavior<CircleImageView> { @Override

    public boolean layoutDependsOn(
 CoordinatorLayout parent, CircleImageView, child, View dependency) { return dependency instanceof Toolbar; } 
 
 public boolean onDependentViewChanged(
 CoordinatorLayout parent, CircleImageView avatar, View dependency) {
 modifyAvatarDependingDependencyState(avatar, dependency); } }
  8. 
 public static class AvatarImageBehavior extends 
 CoordinatorLayout.Behavior<CircleImageView> { @Override

    public boolean layoutDependsOn(
 CoordinatorLayout parent, CircleImageView, child, View dependency) { return dependency instanceof Toolbar; }
 
 public boolean onDependentViewChanged(
 CoordinatorLayout parent, CircleImageView avatar, View dependency) {
 modifyAvatarDependingDependencyState(avatar, dependency); } }
  9. Multiple Parallax Effects https://github.com/saulmm/CoordinatorBehaviorExample 
 public  void  initParallaxValues  {
  

       CollapsingToolbarLayout.LayoutParams  lp1  =
              (CollapsingToolbarLayout.LayoutParams)  
                        mPetImage.getLayoutParams();
 
      CollapsingToolbarLayout.LayoutParams  lp2  =
              (CollapsingToolbarLayout.LayoutParams)  
                        mPetTextContainer.getLayoutParams();
 
      lp1.setParallaxMultiplier(0.9f);        lp2.setPArallaxMultiplier(0.3f);
 
      mPetImage.setLayoutParams(lp1);
      mPetTextContainer.setLayoutParams(lp2);
 }
  10. <Space        android:layout_width=“@dimen/spacing_left”        android:layout_height=“wrap_content”
  

       /> <TextView        android:layout_width=“wrap_content”        android:layout_height=“wrap_content”
      style=“@style/myTitleText”
      /> <TextView        android:layout_width=“wrap_content”        android:layout_height=“wrap_content”
      style=“@style/mSubTitleText
      /> <dimen  name=“spacing_left”>56dp</dimen>
  11. <Space        android:layout_width=“wrap_content”        android:layout_height=“wrap_content”
  

       style=“@style/Widget.Appcompat.Toolbar.Button.Navigation
      /> <TextView        android:layout_width=“wrap_content”        android:layout_height=“wrap_content”
      style=“@style/TextAppearance.Appcompat.Widget.ActionBar.Title”
      /> <TextView        android:layout_width=“wrap_content”        android:layout_height=“wrap_content”
      style=“@style/TextAppearance.Appcompat.Widget.ActionBar.Subtitle”
      /> Reuse available styles
  12. <!—-­‐Spacing  —>   <dimen  name=“spacing_micro”>2dp</dimen>
 <dimen  name=“spacing_small”>4dp</dimen>
 <dimen  name=“spacing_medium”>8dp</dimen>
 <dimen

     name=“spacing_large”>16dp</dimen>
 <dimen  name=“spacing_huge”>32dp</dimen> <!—-­‐Strings  —>   <string  name=“error.empty”>No  results</string>   <string  name=“error.login”>You  need  to  be  logged</string>   <string  name=“error.network”>Network  error</string>   <string  name=“error.network.films”>Couldn’t  fetch  films</string>   <string  name=“error.network.actor”>Couldn’t  fetch  %s  data</string> Organise your resources, DRY https://github.com/futurice/android-best-practices <!—-­‐Font  sizes  —>   <dimen  name=“font_size_micro”>12sp</dimen>
 <dimen  name=“font_size_small”>14sp</dimen>
 <dimen  name=“font_size_medium”>16sp</dimen>
 <dimen  name=“font_size_large”>18sp</dimen>
 
 
 <!—-­‐Elevation  —>   <dimen  name=“elevation_micro”>2dp</dimen>
 <dimen  name=“elevation_small”>4dp</dimen>
 <dimen  name=“elevation_medium”>8dp</dimen>
 <dimen  name=“elevation_large”>12dp</dimen>
 <dimen  name=“elevation_huge”>16dp</dimen>
  13. <style  name=“TextAppearance”  parent=“TextAppearance.AppCompat”/>   <style  name=“TextAppearance.Header”>        <item

     name=“android:textColor”>?colorAccent</item>        <item  name=“android:fontFamily”>sans-­‐serif-­‐medium</item>        <item  name=“android:textAllCaps”>true</item>   </style>   <style  name=“TextAppearance.Field”>        <item  name=“android:textColor”>@color/gray_dark</item>   </style>   <style  name=“TextComponent”>        <item  name=“android:minHeight”>@dimen/grid_size_medium</item>        <item  name=“android:gravity”>center_vertical</item>   </style>   <style  name=“TextComponent.Header”>      <item  name=“android:textAppearance”>@style/TextAppearance.Header</item>   </style>   <style  name=“TextComponent.Field”>      <item  name=“android:textAppearance”>@style/TextAppearance.Field</item>   </style>   <style  name=“TextComponent.Field.Clickable”>        <item  name=“android:clickable”>true</item>        <item  name=“android:background”>?android:attr/selectableItemBackground</item>   </style>  
  14. public  interface  MoviewView  {
      public  void  showMovieTitle  (String

     title);
 
      public  void  showMovieImage  (String  imageUri);
          public  void  showTagLine  (String  tagLine);
 
      public  void  showDescription  (String  descrpition);
 
      public  void  showWebPage  (String  webPage);   
      public  void  showProducer  (String  producer);  
 
      public  void  showLoadingIndicator  ();
 
      public  void  hideLoadingIndicator  ();
 }
  15. public  class  MovieActivity  implements  MovieView  {
      private  MoviePresenter

     mPresenter;
 
      public  void  onCreate  ()  {  …  mPresenter.onCreate();  }  
 
      public  void  onResume  ()  {  …  mPresenter.onResume();  }
 
      public  void  showMovieTitle  (String  title)  {
            mTitleTextView.setText(title);
      }
 
      public  void  showMovieImage  (String  imageUri)  {
            Glide.with(this).load(imageUri).into(mFilmImageView);
      }
 
        public  void  showLoadingIndicator  ()  {
            mLoadingIndicator.setVisibility(View.VISIBLE);
      }
 
      public  void  hideLoadingIndicator  ()  {
            mLoadingIndicator.setVisibility(View.GONE);
      }
 }
  16. public  interface  MoviePresenter  {
      private  MovieView  mMoviewView;
  

       private  MovieUsecase  mMovieUsecase;
 
      public  void  MoviePresenter  (MovieView  movieView)  {
            mMovieView  =  movieView;
      }
 
      public  void  onCreate  ()  {              mMoviewView.showLoadingMoview();              mMovieUsecase.subscribe(movie::bindMovie)        }  
              public  void  bindMovie  (Movie  movie)  {
            mMovieView.hideLoadingIndicator();
            mMovieView.showMovieTitle(movie.getTitle());
            mMovieView.showMovieImage(movie.getImage());
      }
 }
  17. public  class  MovieUsecase  implements  Usecase<Movie>  {
      private  Repository

     mRepository;          public  Observable<Movie>  execute  {
            return  mRepository.getRandomMovie();
      }
 }
  18. //  settings.gradle   include:  ‘:presentation’,          

             ‘:domain’,
                  ‘:model’,                    ‘:common’ //  your  module  build.gradle   compile  project:  ‘(:{your  module})’     Layers as modules