Material Design Custom Views

Report 3 Downloads 305 Views
Material Design Custom Views +SaidTahsinDane @tasomaniac

Android Views What is View? Android SDK has some built-in Views TextView, ImageView, Button ViewGroup, LinearLayout, RelativeLayout ViewStub

Isn’t the framework good enough? @tasomaniac @tasomaniac

Android Views What are they responsible for? Attachment/Detachment Measuring, Drawing Saving UI state Handling Touch Events Listeners/Callbacks @tasomaniac @tasomaniac

Why custom Views?

Why custom Views? View reuse Unique presentation Custom interactions Layout Optimizations Performance Build UIs that are not naturally possible @tasomaniac @tasomaniac

ProfileView

@tasomaniac @tasomaniac

@tasomaniac

TextView nameView = (TextView) profileView.findViewById(android.R.id. text1); ImageView iconView = (ImageView) profileView.findViewById(android.R.id. icon); nameView.setText(user.getName()); iconView.setImageResource(user.getIcon());

@tasomaniac

Ex: ProfileView public class ProfileView extends LinearLayout { public ProfileView(Context context) { super(context); } public ProfileView(Context context , AttributeSet attrs) { super(context, attrs); } }

@tasomaniac @tasomaniac

public class ProfileView extends LinearLayout { private final TextView textView; private final ImageView iconView; private User user; public ProfileView(Context context, AttributeSet attr) { super(context, attr); setOrientation(LinearLayout.HORIZONTAL); setGravity(Gravity.CENTER); inflate(context, R.layout.profile_view, this); textView = (TextView) findViewById(android.R.id.text1); iconView = (ImageView) findViewById(android.R.id.icon); } public void setUser(User user) { this.user = user; textView.setText(user.getName()); iconView.setImageResource(user.getIcon()); } } @tasomaniac

android:orientation="horizontal"> @tasomaniac

public class ProfileView extends LinearLayout implements View.OnClickListener { public ProfileView(Context context, AttributeSet attr) { super(context, attr); ... setOnClickListener(this); } ... public void onClick(View v) { if (this.user != null) { Intent i = new Intent(getContext(), ProfileActivity.class); i.putExtra("user", this.user); getContext().startActivity(i); } } }

@tasomaniac

Save State Data model should be separate from view state Save user interactions in progress Scroll position Active selections Active modes Uncommitted user input e.g. text entered @tasomaniac @tasomaniac

Saving State of your View @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable( "user", this.user); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { Bundle bundle = (Bundle) state ; this.user = bundle.getParcelable( "user"); }

@tasomaniac @tasomaniac

Material Design

Material Design! Yey! Use AppCompat to support Material Design Ripple Effects Widget Tinting Palette & ColorUtils Theme support

@tasomaniac @tasomaniac

Change the theme first!

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> @color/colorPrimary @color/colorPrimaryDark @color/colorAccent

@tasomaniac @tasomaniac

Use AppCompatActivity

This will automatically use Material Design!

public class MainActivity extends AppCompatActivity { }

@tasomaniac @tasomaniac

In your custom Views Extend your Views from AppCompat alternatives. AppCompatButton AppCompatCheckBox AppCompatEditText AppCompatSpinner AppCompatTextView ...

@tasomaniac @tasomaniac

Ripple Effect How to keep ripples in Custom Views? Be backward compatible

@tasomaniac @tasomaniac

Ripple Effect Use android:background="?attr/selectableItemBackground"

or android:background="?attr/selectableItemBackgroundBorderless"

as your background

@tasomaniac @tasomaniac

Ripple Effect For complicated views with images: …………

@tasomaniac @tasomaniac

Fixes Holo too!

@tasomaniac @tasomaniac

Widget Theming

How do you normally achieve this? Introduced in Lollipop Available for all thanks to AppCompat @tasomaniac @tasomaniac

Widget Theming



@tasomaniac

What about selected states?

Normal behavior

@tasomaniac @tasomaniac

What about selected states?

Find the 3 differences in these images?

@tasomaniac @tasomaniac

Widget Theme’s to the rescue!

@tasomaniac @tasomaniac

Attrs in AppCompat It now contains almost all the attrs you may need. ?attr/actionBarSize ?attr/listPreferredItemHeight ?attr/listChoiceBackgroundIndicator

or ?android:attr/textColorPrimary

@tasomaniac @tasomaniac

Access theme attrs Utility methods to access your theme ThemeUtils.getThemeAttrColor(context, R.attr.colorPrimary);

Colors and Drawables ContextCompat.getColor(context, R.color.itemBackgroundColor); ContextCompat.getDrawable(context, R.color.itemBackground);

@tasomaniac

Widget Tinting

First introduced in Lollipop Available backward-compatible with AppCompat.

@tasomaniac @tasomaniac

Widget Tinting // Wrap the drawable so that future tinting calls work // on pre-v21 devices. Always use the returned drawable. drawable = DrawableCompat.wrap(drawable);

DrawableCompat.setTint(drawable, Color.RED); // ...or a tint list DrawableCompat.setTintList(drawable, myColorStateList);

@tasomaniac @tasomaniac

Palette & ColorUtils

Get color palette from your pics Vibrant, Muted Swatch

@tasomaniac @tasomaniac

Palette

Palette.Swatch swatch = palette.getVibrantSwatch(); if (swatch != null) { titleView.setBackgroundColor(swatch.getRgb()); titleView.setTextColor(swatch.getTitleTextColor()); }

@tasomaniac @tasomaniac

ColorUtils int textColor = Color.WHITE; float minContrastRatio = 4.5f; // Min contrast ration of 1:4.5 int minAlpha = ColorUtils.calculateMinimumAlpha( textColor, backgroundColor, minContrastRatio); if (minAlpha != -1) { // There is an alpha value which has enough contrast, use it! return ColorUtils.setAlphaComponent(textColor, minAlpha); }

@tasomaniac #dfua

Thank you! Questions?

+SaidTahsinDane @tasomaniac

Recommend Documents