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

Abstract UI Concepts

Abstract UI Concepts

A different way of thinking about writing UI code.

Sriram Ramani

December 06, 2014
Tweet

More Decks by Sriram Ramani

Other Decks in Programming

Transcript

  1. SHOCK SPOCK A piece of text that extends couple of

    lines. This is the core of the app as this provides the information to the user.
  2. ListView Recycling ITEM 1 ITEM 2 ITEM 3 ITEM 4

    ITEM 5 ITEM 6 ITEM 7 ITEM 8 ITEM 8 ITEM 8
  3. ListView Recycling USER NAME A piece of text that extends

    couple of lines. This is the core of the app as this provides the information to the user. USER NAME A piece of text that extends couple of lines. This is the core of the app as this provides the information to the user. USER NAME A piece of text that extends couple of lines. This is the core of the app as this provides the information to the user. USER NAME A piece of text that extends couple of lines. This is the core of the app as this provides the information to the user. USER NAME A piece of text that extends couple of lines. This is the core of the app as this provides the information to the user. USER NAME
  4. SHOCK SPOCK A piece of text that extends couple of

    lines. This is the core of the app as this provides the information to the user.
  5. ListView Recycling USER NAME A piece of text that extends

    couple of lines. This is the core of the app as this provides the information to the user. USER NAME A piece of text that extends couple of lines. This is the core of the app as this provides the information to the user. USER NAME A piece of text that extends couple of lines. This is the core of the app as this provides the information to the user. USER NAME USER NAME A piece of text that extends couple of lines. This is the core of the app as this provides the information to the user. USER NAME A piece of text that extends couple of lines. This is the core of the app as this provides the information to the user.
  6. public enum ITEM_TYPES { HEADER, CONTENT, SECONDARY_INFO, FEEDBACK_BAR } @Override

    public int getViewTypeCount() { return ITEM_TYPES.values().length; } @Override public int getItemViewType(int position) { return ITEM_TYPES.values()[position % getViewTypeCount()]; } @Override public View getView(int position, View convertView, ViewGroup parent) { // Bind based on the item type. } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  7. Advantages ▪ Faster binding time ▪ Less time to measure

    ▪ Less time to draw each row ▪ More re-usable rows
  8. LinearLayout weights Shock Spock 2 hr • San Francisco, CA

    Thumbnail LinearLayout (Outer) Title Subtitle Menu LinearLayout (Inner)
  9. LinearLayout weights > LinearLayout (Outer) > Thumbnail > LinearLayout (Inner)

    > Title > Subtitle > Title > Subtitle > Menu > LinearLayout (Inner) > Title > Subtitle Shock Spock 2 hr • San Francisco, CA
  10. RelativeLayout Shock Spock 2 hr • San Francisco, CA Title

    Subtitle Thumbnail Menu RelativeLayout
  11. RelativeLayout > RelativeLayout > Menu > Thumbnail > Subtitle >

    Title > Title > Subtitle > Menu > Thumbnail Shock Spock 2 hr • San Francisco, CA
  12. Custom ViewGroup > CustomViewGroup > Thumbnail > Menu > Title

    > Subtitle Shock Spock 2 hr • San Francisco, CA
  13. @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthConstraints

    = getPaddingLeft() + getPaddingRight(); int heightConstraints = getPaddingTop() + getPaddingBottom(); // Measure the thumbnail. measureChildWithMargins( mThumbnailView, widthMeasureSpec, widthConstraints, heightMeasureSpec, heightConstraints); widthConstraints += mThumbnailView.getMeasuredWidth(); // Measure the title. measureChildWithMargins( mTitleView, widthMeasureSpec, widthConstraints, heightMeasureSpec, heightConstraints); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
  14. @Override protected void measureChildWithMargins( View child, int parentWidthMeasureSpec, int widthConstraints,

    int parentHeightMeasureSpec, int heightConstraints) { MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, widthConstraints + lp.leftMargin + lp.rightMargin, lp.width); int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, heightConstraints + lp.topMargin + lp.bottomMargin, lp.height); child.measure(childWidthMeasureSpec, childHeightMeasureSpec); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  15. SHOCK SPOCK A piece of text that extends couple of

    lines. This is the core of the app as this provides the information to the user. 1 2 3 4 5
  16. TextViews Bacon ipsum dolor sit amet spare ribs pork tongue,

    hamburger biltong rump shoulder turkey ham hock beef tri-tip pork chop jerky fatback.
  17. TextViews Bacon ipsum dolor sit amet spare ribs pork tongue,

    hamburger biltong rump shoulder turkey ham hock beef tri-tip pork chop jerky fatback.
  18. ListView Recycling ITEM 1 ITEM 2 ITEM 3 ITEM 4

    ITEM 5 ITEM 6 ITEM 7 ITEM 8 ITEM 8 ITEM 8
  19. @Override public void setText(CharSequence text) { // Store the text.

    checkForRelayout(); } private void checkForRelayout() { // Make new layout for the new text. makeNewLayout(want, …, width, …); } 1 2 3 4 5 6 7 8 9 10 11 12
  20. public class TextLayoutView extends View { private Layout mLayout; public

    void setText(CharSequence text, String key) { Layout layout = SHARED_LAYOUT_CACHE.get(key); if (layout == null) { // Better to do this in onMeasure() mLayout = new StaticLayout(…); } else { mLayout = layout; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mLayout.draw(canvas); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  21. Advantages ▪ Less object creation ▪ Layout measuring cost is

    saved ▪ Works with Spannables too ▪ Can hack it work for ClickableSpans
  22. public class TextLayoutView extends View { private Layout mLayout; public

    void setText(CharSequence text, String key) { Layout layout = SHARED_LAYOUT_CACHE.get(key); if (layout == null) { // Better to do this in onMeasure() mLayout = new StaticLayout(…); } else { mLayout = layout; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mLayout.draw(canvas); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  23. public class TextLayoutView extends View { private Layout mLayout; private

    Picture mPicture; private boolean mRecorded = false; @Override protected void onDraw(Canvas canvas) { if (!mRecorded) { Canvas pictureCanvas = mPicture.beginRecording( canvas.getWidth(), canvas.getHeight()); super.onDraw(pictureCanvas); mLayout.draw(pictureCanvas); mPicture.endRecording(); mRecorded = true; } mPicture.draw(canvas); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
  24. public class SpriteImageView extends ImageView { private WeakReference<Bitmap> mBitmap; @Override

    public void onDraw(Canvas canvas) { // Get the destination rectangle. getDrawingRect(mDestinationRect); // Draw the bitmap. canvas.drawBitmap(mBitmap.get(), mSourceRect, mDestinationRect, null); } public void setCoordinates(int left, int top, int width, int height) { mSourceRect.set(left, top, left + width, top + height); invalidate(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  25. Advantages ▪ Pay the cost of reading bitmap once ▪

    Need not be in Android resource cache ▪ Less commands sent to GPU ▪ Same texture re-used
  26. private void tintGlyph(int tintColor) { // Create a color filter.

    ColorFilter colorFilter = new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN); // Set it on the drawable. mDrawable.setColorFilter(colorFilter); } 1 2 3 4 5 6 7 8 9
  27. <selector> <!— Selected —> <item android:state_selected=“true” android:state_enabled=“true” android:color=“@color/blue” /> <!—

    Enabled —> <item android:state_enabled=“true” android:color=“@color/white” /> <!— Disabled —> <item android:color=“@color/grey” /> </selector> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  28. public class TintImageView extends ImageView { private ColorStateList mTintColor; @Override

    protected void drawableStateChanged() { super.drawableStateChanged(); if (mTintColor != null) { // Get the color for the state. int[] state = getDrawableState(); int tintColor = mTintColor.getColorForState(state, 0); // Create a color filter. ColorFilter colorFilter = new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN); // Set it on the image. setColorFilter(colorFilter); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  29. Advantages ▪ Cuts down resources in half (or even more)

    ▪ Can be combined with sprites ▪ Only one bitmap is loaded even for StateListDrawable