custom ui components at android only 2011
Post on 17-May-2015
6.040 Views
Preview:
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