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.

Avatar for Sriram Ramani

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