custom ui components at android only 2011

Post on 17-May-2015

6.044 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Custom UI Components

 

Widgets and Layouts are used to construct a UI.• A Widget is a UI element, like a text field or button

• Layouts are invisible containers, like LinearLayout or RelativeLayout

Widget != Widget

Widget

Layout

View Hierarchy

Why build custom components? Isn't there enough already?

Free

37 SEK

public void onCreate(Bundle savedInstanceState) {    ....    mPriceTextView = (TextView) findViewById(R.id.price);    mPriceTextView.addTextChangedListener(new TextWatcher() {        @Override        public void onTextChanged(CharSequence s, int start,                int before, int count) {            if (getText(R.string.free).equals(s.toString())) {                mPriceTextView.setTextColor(                    getResources().getColor(R.color.free));            } else {                mPriceTextView.setTextColor(                    getResources().getColor(R.color.rent));            }        }

        @Override        public void beforeTextChanged(CharSequence s, int start,                int count, int after) { }

        @Override        public void afterTextChanged(Editable s) { }    });}

We can solve this problem with custom components.

When building a fully customized component extend View.

Need to override onDraw to be able to show something.• 2D graphics

• Text in different variations

• Other components

• Or pretty much anything else

onMeasure should be overridden by subclasses to provide measurement of their contents.

Custom widgets can really be as complicated as you need them to be.

Not so fully customized components.

PriceViewpublic class PriceView extends TextView implements TextWatcher {

    public PriceView(Context context, AttributeSet attrs) {        super(context, attrs);    }

    @Override    public void onTextChanged(CharSequence s, int start,            int before, int count) {        if (!TextUtils.isEmpty(s) && getResources()                .getText(R.string.free).equals(s.toString())) {            setTextColor(getResources().getColor(R.color.free));        } else {            setTextColor(getResources().getColor(R.color.rent));        }    }

    @Override    public void afterTextChanged(Editable s) {    }

    @Override    public void beforeTextChanged(CharSequence s, int start,            int count, int after) {    }}

<com.markupartist.demo.ao11.demo2.PriceView     android:id="@+id/price"    android:layout_width="fill_parent"     android:layout_height="wrap_content"     android:text="@string/free"    android:textSize="30sp"    />

<TextView     android:id="@+id/price"    android:layout_width="fill_parent"     android:layout_height="wrap_content"     android:text="@string/free"    android:textSize="30sp"    />

Demo 

Compound Components

priceView.setPrice(    new Price(amount, currency));

 <LinearLayout     android:layout_width="wrap_content"     android:layout_height="wrap_content"    >    <TextView         android:id="@+id/amount"        android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:textColor="@color/rent"        android:textSize="30sp"        />    <TextView        android:id="@+id/currency"        android:paddingLeft="5dip"        android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:textSize="30sp"        /></LinearLayout>

public class PriceView extends LinearLayout {

    private TextView mAmount;

    private TextView mCurrency;

    public PriceView(Context context, AttributeSet attrs) {

        super(context, attrs);

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(

                Context.LAYOUT_INFLATER_SERVICE);

        LinearLayout priceView = (LinearLayout) inflater.inflate(

                R.layout.priceview, null);

        mAmount = (TextView) priceView.findViewById(R.id.amount);

        mCurrency = (TextView) priceView.findViewById(R.id.currency);

    }

    public void setPrice(Price price) {

        mAmount.setText(price.getAmount());

        mCurrency.setText(price.getCurrency());

    }

}

Demo 

How to debug and optimize the UI?

$ ./tools/layoutopt

$ ./tools/hierarchyviewer

DemoHiearchy Viewer

Reduce the number of views in the view tree with <merge>

<LinearLayout    android:layout_width="wrap_content"     android:layout_height="wrap_content">    <TextView         android:id="@+id/amount"        android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:textColor="@color/rent"        android:textSize="30sp"/>    <TextView        android:id="@+id/currency"        android:paddingLeft="5dip"        android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:textSize="30sp"/></LinearLayout>

<merge     <TextView         android:id="@+id/amount"        android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:textColor="@color/rent"        android:textSize="30sp"/>    <TextView        android:id="@+id/currency"        android:paddingLeft="5dip"        android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:textSize="30sp"/></merge>

And...

inflater.inflate(    R.layout.priceview,    null);

inflater.inflate(    R.layout.priceview,    this,    true);

DemoHiearchy Viewer

isInEditMode()

 

Photo by anarchosyn, http://www.flickr.com/photos/24293932@N00/4530523480/

Sets of properties that specifies the look of a Widget. This can be properties such a width, height and colors. The concept is similar to CSS and separates presentation from the content.

Styles and Themes• Custom attributes

• Styles

• Themes

Custom attributes

<com.markupartist.demo.ao11.demo5.PriceView    android:id="@+id/price"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    app:amountText="37"    app:currencyText="SEK"    />

Goes into res/values/attrs.xml• Declared in the top <resources or in the <declare-stylable>

element

• The <attr> element has two attributes name and format– Name is used when referring from code e.g.

R.stylable.PriceView_amountText

– Format defines the value it represents• Reference

• Color

• String

• Boolean

• And a few more

Custom Attributes<resources>    <attr name="amountStyle" format="reference" />      <declare-styleable name="PriceView">        <attr name="amountText" format="string" />    </declare-styleable></resources>

public PriceView(Context context, AttributeSet attrs) {    super(context, attrs);    TypedArray array = context.obtainStyledAttributes(        attrs, R.styleable.PriceView, 0, 0);    String amountText =        array.getString(R.styleable.PriceView_amountText);    // Set amount to the view...    array.recycle();}

Styles goes into res/values/styles.xml

<style name="PriceText" parent="android:style/Widget.TextView">    <item name="android:layout_width">wrap_content</item>    <item name="android:layout_height">wrap_content</item>    <item name="android:textSize">30sp</item></style>

<style name="AmountText" parent="@style/PriceText">    <item name="android:textColor">@color/rent</item></style>

<style name="CurrencyText" parent="@style/PriceText">    <item name="android:paddingLeft">5dip</item></style>

<merge>    <TextView android:id="@+id/amount" style="@style/AmountText"/>    <TextView android:id="@+id/currency" style="@style/CurrencyText"/></merge>

A problem with styles is that it's hard to change the style of an View that's included within a compound component. And we can't change the style in runtime.

Themes, a style that’s applied to a whole Activity or Application

• With custom attributes we can provide a way to style views within compound components

• Makes it easier for others to override default styles

• This can be hooks for styles, dimensions, colors...

<attr name="amountStyle" format="reference" />

android:theme="@style/AO11Theme"

<style name="AO11Theme" parent="android:style/Theme">  <item name="amountStyle">@style/AmountText</item></style>

<TextView android:id="@+id/priceview_amount"  style="?attr/amountStyle" />

android:theme="@style/AO11ThemeCustom"

<style name="AO11ThemeCustom" parent="android:style/Theme.Light">  <item name="amountStyle">@style/CustomAmountText</item></style>

How do we make a custom component available for other applications.• We can't use JAR

• We don't want to copy-paste resources

Library Projects• Holds shared code and resources

• Resources are merged at build time

• Can be used for– Custom components– White label apps– Paid and free versions of the same app

Thank you

https://github.com/johannilsson/ao11

top related