Share
Embed
Custom Views for Profit and Pleasure (TC GDG)
All about custom Views and their uses.
Daniel Lew
September 02, 2014
Transcript
39 slides
-
Custom Views (as viewed by your average Android developer) Image
source: http://goo.gl/JLdYHW -
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) -
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 reuse • Encapsulation • Compound Views • XML
styling <net.danlew.app.FontTextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:font="comicSans" /> ! <net.danlew.app.FontTextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:font="papyrus" /> -
• View reuse • Encapsulation • Compound Views • XML
styling • Custom drawing -
• View reuse • Encapsulation • Compound Views • XML
styling • Custom drawing • Performance -
• View reuse • Encapsulation • Compound Views • XML
styling • Custom drawing • Performance • Awesomeness -
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) -
Step 2: Constructor public class CustomView extends View {
public CustomView(Context context) { super(context); } } -
Without Custom Views <LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content" android:gravity="center" android:orientation="vertical"> ! <ImageView android:id="@+id/icon" android:layout_width="128dp" android:layout_height="128dp" /> ! <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:textSize="22sp" /> ! </LinearLayout> -
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()); -
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); } } -
Compound Views <merge> ! <ImageView
android:id="@+id/icon" android:layout_width="128dp" android:layout_height="128dp" /> ! <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:textSize="22sp" /> ! </merge> -
Compound Views UserView userView = new UserView(context); userView.setName(user.getName());
userView.setIcon(user.getIcon()); -
Encapsulation public class UserView extends LinearLayout { !
/* ...same code as before... */ ! public void bind(User user) { mIconView.setImageResource(user.getIcon()); mNameView.setText(user.getName()); } } -
XML Styling <resources> <declare-‐styleable name="UserView">
<attr name="tint" format="color" /> </declare-‐styleable> </resources> -
XML Styling <net.danlew.customviews.view.UserView 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" /> -
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); } } -
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) -
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 -
Performance • UserView is simple… • …don’t prematurely optimize! •
One possibility: customized onLayout()