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

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 full-size slide

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

    View full-size 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 full-size 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 full-size slide

  5. Library Views
    !=
    Custom Views

    View full-size slide

  6. Why custom Views?

    View full-size slide

  7. • View reuse

    View full-size slide

  8. • View reuse
    • Encapsulation

    View full-size slide

  9. • View reuse
    • Encapsulation
    • Compound Views

    View full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  14. One downside…

    View full-size slide

  15. …no custom View composition

    View full-size 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 full-size slide

  17. A Simple Custom View

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  21. You’re done!

    View full-size slide

  22. UserView
    Our brave illustrative warrior

    View full-size slide

  23. Without Custom Views

    View full-size 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 full-size 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 full-size 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 full-size 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 full-size slide

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

    View full-size 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 full-size slide

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

    View full-size slide

  31. XML Styling
     
             
                     
             

    View full-size slide

  32. 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 full-size slide

  33. 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 full-size slide

  34. 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 full-size slide

  35. Custom Drawing

    View full-size slide

  36. 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 full-size slide

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

    View full-size slide

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

    View full-size slide