$30 off During Our Annual Pro Sale. View Details »

Custom Views for Profit and Pleasure (TC GDG)

Daniel Lew
September 02, 2014

Custom Views for Profit and Pleasure (TC GDG)

All about custom Views and their uses.

Daniel Lew

September 02, 2014
Tweet

More Decks by Daniel Lew

Other Decks in Technology

Transcript

  1. Custom Views for Profit and Pleasure
    September 2, 2014

    View Slide

  2. Custom Views
    (as viewed by your average Android developer)
    Image source: http://goo.gl/JLdYHW

    View Slide

  3. Framework Views are huge!
    View Lines
    View 19,572
    TextView 9,220
    ImageView 1,260
    ViewGroup 6,771
    LinearLayout 1,898
    RelativeLayout 1,812
    AdapterView 1,208
    AbsListView 6,919
    ListView 3,799
    (Data as of API 19)

    View Slide

  4. Too Many Methods!
    Category Methods
    Creation
    Constructors
    onFinishInflate()
    Layout
    onMeasure()
    onLayout()
    Drawing
    onSizeChanged()
    onDraw()
    Event processing
    onKeyDown()
    onKeyUp()
    onTrackballEvent()
    onTouchEvent()
    Focus
    onFocusChanged()
    onWindowFocusChanged()
    Attaching
    onAttachedToWindow()
    onDetachedFromWindow()
    onWindowVisibilityChanged()

    View Slide

  5. Library Views
    !=
    Custom Views

    View Slide

  6. Why custom Views?

    View Slide

  7. • View reuse

    View Slide

  8. • View reuse
    • Encapsulation

    View Slide

  9. • View reuse
    • Encapsulation
    • Compound Views

    View Slide

  10. • View reuse
    • Encapsulation
    • Compound Views
    • XML styling
           android:layout_width="wrap_content"  
           android:layout_height="wrap_content"  
           app:font="comicSans"  />  
    !
           android:layout_width="wrap_content"  
           android:layout_height="wrap_content"  
           app:font="papyrus"  />

    View Slide

  11. • View reuse
    • Encapsulation
    • Compound Views
    • XML styling
    • Custom drawing

    View Slide

  12. • View reuse
    • Encapsulation
    • Compound Views
    • XML styling
    • Custom drawing
    • Performance

    View Slide

  13. • View reuse
    • Encapsulation
    • Compound Views
    • XML styling
    • Custom drawing
    • Performance
    • Awesomeness

    View Slide

  14. One downside…

    View Slide

  15. …no custom View composition

    View Slide

  16. Avoid Custom Views
    • …when you can set a listener:
    !
           view.setOnClickListener(new  OnClickListener()  {  ...  });  
    • …when you could just use a custom Drawable:
    !
           imageView.setImageDrawable(new  CustomDrawable());  
    (See “Mastering Android drawables”: http://goo.gl/ENfzW6)

    View Slide

  17. A Simple Custom View

    View Slide

  18. Step 1: Subclass
    public  class  CustomView  extends  View  {  
    !
    !
    !
    }

    View Slide

  19. Step 2: Constructor
    public  class  CustomView  extends  View  {  
           public  CustomView(Context  context)  {  
                   super(context);  
           }  
    }

    View Slide

  20. Step 3: Add
    CustomView  customView  =  new  CustomView(context);  
    viewGroup.addView(customView);

    View Slide

  21. You’re done!

    View Slide

  22. UserView
    Our brave illustrative warrior

    View Slide

  23. Without Custom Views

    View Slide

  24. Without Custom Views
           android:layout_width="wrap_content"  
           android:layout_height="wrap_content"  
           android:gravity="center"  
           android:orientation="vertical">  
    !
                           android:id="@+id/icon"  
                   android:layout_width="128dp"  
                   android:layout_height="128dp"  />  
    !
                           android:id="@+id/name"  
                   android:layout_width="wrap_content"  
                   android:layout_height="wrap_content"  
                   android:layout_marginTop="4dp"  
                   android:textSize="22sp"  />  
    !

    View Slide

  25. Without Custom Views
    View  userView  =  LayoutInflater.from(context)  
           .inflate(R.layout.user_view,  parent,  false);  
    !
    TextView  nameView  =  (TextView)  view.findViewById(R.id.name);  
    nameView.setText(user.getName());  
    !
    ImageView  iconView  =  (ImageView)  view.findViewById(R.id.icon);  
    iconView.setImageResource(user.getIcon());

    View Slide

  26. Compound Views
    public  class  UserView  extends  LinearLayout  {  
    !
           private  ImageView  mIconView;  
           private  TextView  mNameView;  
    !
           public  UserView(Context  context)  {  
                   super(context);  
    !
                   setOrientation(LinearLayout.VERTICAL);  
                   setGravity(Gravity.CENTER);  
    !
                   LayoutInflater.from(context).inflate(R.layout.user_view_merge,  this);  
                   mIconView  =  (ImageView)  findViewById(R.id.icon);  
                   mNameView  =  (TextView)  findViewById(R.id.name);  
           }  
    !
           public  void  setIcon(int  drawable)  {  
                   mIconView.setImageResource(drawable);  
           }  
    !
           public  void  setName(CharSequence  name)  {  
                   mNameView.setText(name);  
           }  
    }

    View Slide

  27. Compound Views
     
    !
                         android:id="@+id/icon"  
                   android:layout_width="128dp"  
                   android:layout_height="128dp"  />  
    !
                           android:id="@+id/name"  
                   android:layout_width="wrap_content"  
                   android:layout_height="wrap_content"  
                   android:layout_marginTop="4dp"  
                   android:textSize="22sp"  />  
    !

    View Slide

  28. Compound Views
    UserView  userView  =  new  UserView(context);  
    userView.setName(user.getName());  
    userView.setIcon(user.getIcon());

    View Slide

  29. Encapsulation
    public  class  UserView  extends  LinearLayout  {  
    !
           /*  ...same  code  as  before...  */      
    !
           public  void  bind(User  user)  {  
                   mIconView.setImageResource(user.getIcon());  
                   mNameView.setText(user.getName());  
           }  
    }

    View Slide

  30. Encapsulation
    UserView  userView  =  new  UserView(this);  
    userView.bind(user);

    View Slide

  31. XML Styling

    View Slide

  32. XML Styling
     
             
                     
             

    View Slide

  33. XML Styling
           xmlns:android="http://schemas.android.com/apk/res/android"  
           xmlns:app="http://schemas.android.com/apk/res-­‐auto"  
           android:layout_width="wrap_content"  
           android:layout_height="wrap_content"  
           app:tint="#500F"  />

    View Slide

  34. Reading Styles in Code
    public  class  UserView  extends  LinearLayout  {  
    !
           public  UserView(Context  context,  AttributeSet  attrs)  {  
                   super(context,  attrs);  
    !
                   /*  ...Same  constructor  code  as  before...  */  
    !
                   TypedArray  ta  =  context.obtainStyledAttributes(attrs,    
                           R.styleable.UserView);  
                   setTint(ta.getColor(R.styleable.UserView_tint,  
                           Color.TRANSPARENT));  
                   ta.recycle();  
           }  
    !
           public  void  setTint(int  color)  {  
                   mIconView.setColorFilter(color);  
           }  
    }

    View Slide

  35. Note on Constructors
    • Java constructor:
    !
           public  View(Context  context)  
    • XML constructor:
    !
           public  View(Context  context,  AttributeSet  attrs)  
    • XML w/ styled defaults (rarely necessary):
    !
           public  View(Context  context,  AttributeSet  attrs,  int  defStyleAttr)

    View Slide

  36. Custom Drawing

    View Slide

  37. Custom Drawing
    ublic  class  CircleView  extends  View  {  
    !
           @Override  
           protected  void  onDraw(Canvas  canvas)  {  
                   Paint  paint  =  new  Paint();  
    !
                   /*    
                       ...Configure  paint  here  to  draw  icon...  
                       ...yadda  yadda  yadda...  
                   */  
    !
                   int  radius  =  getWidth()  /  2;  
                   canvas.drawCircle(radius,  radius,  radius,  paint);  
           }  
    }
    yadda: http://goo.gl/W8d17V

    View Slide

  38. Performance
    • UserView is simple…
    • …don’t prematurely optimize!
    • One possibility: customized onLayout()

    View Slide

  39. Thank you!
    • Samples: https://github.com/dlew/android-custom-
    views-sample
    • http://danlew.net/
    • @danlew42
    • +DanielLew

    View Slide