diff options
10 files changed, 417 insertions, 15 deletions
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml index 59d21203e..f4e77e037 100644 --- a/samples/ApiDemos/AndroidManifest.xml +++ b/samples/ApiDemos/AndroidManifest.xml @@ -1390,76 +1390,93 @@ </intent-filter> </activity> - <activity android:name=".view.LinearLayout1" android:label="Views/Layouts/LinearLayout/1. Vertical"> + <activity android:name=".view.LinearLayout1" + android:label="Views/Layouts/LinearLayout/01. Vertical"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> - <activity android:name=".view.LinearLayout2" android:label="Views/Layouts/LinearLayout/2. Vertical (Fill Screen)"> + <activity android:name=".view.LinearLayout2" + android:label="Views/Layouts/LinearLayout/02. Vertical (Fill Screen)"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> - <activity android:name=".view.LinearLayout3" android:label="Views/Layouts/LinearLayout/3. Vertical (Padded)"> + <activity android:name=".view.LinearLayout3" + android:label="Views/Layouts/LinearLayout/03. Vertical (Padded)"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> - <activity android:name=".view.LinearLayout4" android:label="Views/Layouts/LinearLayout/4. Horizontal"> + <activity android:name=".view.LinearLayout4" + android:label="Views/Layouts/LinearLayout/04. Horizontal"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> - <activity android:name=".view.LinearLayout5" android:label="Views/Layouts/LinearLayout/5. Simple Form"> + <activity android:name=".view.LinearLayout5" + android:label="Views/Layouts/LinearLayout/05. Simple Form"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> - <activity android:name=".view.LinearLayout6" android:label="Views/Layouts/LinearLayout/6. Uniform Size"> + <activity android:name=".view.LinearLayout6" + android:label="Views/Layouts/LinearLayout/06. Uniform Size"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> - <activity android:name=".view.LinearLayout7" android:label="Views/Layouts/LinearLayout/7. Fill Parent"> + <activity android:name=".view.LinearLayout7" + android:label="Views/Layouts/LinearLayout/07. Fill Parent"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> - <activity android:name=".view.LinearLayout8" android:label="Views/Layouts/LinearLayout/8. Gravity"> + <activity android:name=".view.LinearLayout8" + android:label="Views/Layouts/LinearLayout/08. Gravity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> - <activity android:name=".view.LinearLayout9" android:label="Views/Layouts/LinearLayout/9. Layout Weight"> + <activity android:name=".view.LinearLayout9" + android:label="Views/Layouts/LinearLayout/09. Layout Weight"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> - <activity android:name=".view.LinearLayout10" android:label="Views/Layouts/LinearLayout/10. Background Image"> + <activity android:name=".view.LinearLayout10" + android:label="Views/Layouts/LinearLayout/10. Background Image"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> + <activity android:name=".view.CustomLayoutActivity" + android:label="Views/Layouts/CustomLayout"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.SAMPLE_CODE" /> + </intent-filter> + </activity> <activity android:name=".view.RadioGroup1" android:label="Views/Radio Group"> <intent-filter> diff --git a/samples/ApiDemos/res/drawable/box.xml b/samples/ApiDemos/res/drawable/box.xml index 825de8495..482648bbb 100644 --- a/samples/ApiDemos/res/drawable/box.xml +++ b/samples/ApiDemos/res/drawable/box.xml @@ -18,7 +18,7 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#00000000"/> - <stroke android:width="1dp" color="#ff000000"/> + <stroke android:width="1dp" android:color="#ff000000"/> <padding android:left="1dp" android:top="1dp" android:right="1dp" android:bottom="1dp" /> </shape> diff --git a/samples/ApiDemos/res/drawable/box_white.xml b/samples/ApiDemos/res/drawable/box_white.xml index 9b9b1921c..40b3cfc18 100644 --- a/samples/ApiDemos/res/drawable/box_white.xml +++ b/samples/ApiDemos/res/drawable/box_white.xml @@ -17,5 +17,5 @@ --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> - <stroke android:width="1dp" color="#ffffffff"/> + <stroke android:width="1dp" android:color="#ffffffff"/> </shape> diff --git a/samples/ApiDemos/res/drawable/filled_box.xml b/samples/ApiDemos/res/drawable/filled_box.xml index 75d15a00b..f3839009f 100644 --- a/samples/ApiDemos/res/drawable/filled_box.xml +++ b/samples/ApiDemos/res/drawable/filled_box.xml @@ -18,7 +18,7 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#f0600000"/> - <stroke android:width="3dp" color="#ffff8080"/> + <stroke android:width="3dp" android:color="#ffff8080"/> <corners android:radius="3dp" /> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> diff --git a/samples/ApiDemos/res/drawable/hover_background_active.xml b/samples/ApiDemos/res/drawable/hover_background_active.xml index 8819ce213..0881491f6 100644 --- a/samples/ApiDemos/res/drawable/hover_background_active.xml +++ b/samples/ApiDemos/res/drawable/hover_background_active.xml @@ -16,7 +16,7 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#ffdddd00"/> - <stroke android:width="3dp" color="#ff000000"/> + <stroke android:width="3dp" android:color="#ff000000"/> <corners android:radius="3dp" /> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> diff --git a/samples/ApiDemos/res/drawable/hover_background_inactive.xml b/samples/ApiDemos/res/drawable/hover_background_inactive.xml index 5ddab3a24..0f6cb303f 100644 --- a/samples/ApiDemos/res/drawable/hover_background_inactive.xml +++ b/samples/ApiDemos/res/drawable/hover_background_inactive.xml @@ -16,7 +16,7 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#f0600000"/> - <stroke android:width="3dp" color="#ffff8080"/> + <stroke android:width="3dp" android:color="#ffff8080"/> <corners android:radius="3dp" /> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> diff --git a/samples/ApiDemos/res/layout/custom_layout.xml b/samples/ApiDemos/res/layout/custom_layout.xml new file mode 100644 index 000000000..ff3cfc4bc --- /dev/null +++ b/samples/ApiDemos/res/layout/custom_layout.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- Demonstrates use of CustomLayout --> + +<!-- BEGIN_INCLUDE(Complete) --> +<com.example.android.apis.view.CustomLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res/com.example.android.apis" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <!-- put first view to left. --> + <TextView + android:background="@drawable/filled_box" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:layout_position="left" + android:layout_gravity="fill_vertical|center_horizontal" + android:text="l1"/> + + <!-- stack second view to left. --> + <TextView + android:background="@drawable/filled_box" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:layout_position="left" + android:layout_gravity="fill_vertical|center_horizontal" + android:text="l2"/> + + <!-- also put a view on the right. --> + <TextView + android:background="@drawable/filled_box" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:layout_position="right" + android:layout_gravity="fill_vertical|center_horizontal" + android:text="r1"/> + + <!-- by default views go in the middle; use fill vertical gravity --> + <TextView + android:background="@drawable/green" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="fill_vertical|center_horizontal" + android:text="fill-vert"/> + + <!-- by default views go in the middle; use fill horizontal gravity --> + <TextView + android:background="@drawable/green" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|fill_horizontal" + android:text="fill-horiz"/> + + <!-- by default views go in the middle; use top-left gravity --> + <TextView + android:background="@drawable/blue" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="top|left" + android:text="top-left"/> + + <!-- by default views go in the middle; use center gravity --> + <TextView + android:background="@drawable/blue" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:text="center"/> + + <!-- by default views go in the middle; use bottom-right --> + <TextView + android:background="@drawable/blue" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|right" + android:text="bottom-right"/> + +</com.example.android.apis.view.CustomLayout> +<!-- END_INCLUDE(Complete) --> diff --git a/samples/ApiDemos/res/values/attrs.xml b/samples/ApiDemos/res/values/attrs.xml index 35f224ef5..bf33788cb 100644 --- a/samples/ApiDemos/res/values/attrs.xml +++ b/samples/ApiDemos/res/values/attrs.xml @@ -33,6 +33,19 @@ <attr name="textSize" format="dimension" /> </declare-styleable> + <!-- These are the attributes that we want to retrieve for + view/CustomLayout.java --> +<!-- BEGIN_INCLUDE(CustomLayout) --> + <declare-styleable name="CustomLayoutLP"> + <attr name="android:layout_gravity" /> + <attr name="layout_position"> + <enum name="middle" value="0" /> + <enum name="left" value="1" /> + <enum name="right" value="2" /> + </attr> + </declare-styleable> +<!-- END_INCLUDE(CustomLayout) --> + <!-- These are attributes used with 'DraggableDot' drawables in view/DragAndDropActivity.java and view/DraggableDot.java --> <declare-styleable name="DraggableDot"> diff --git a/samples/ApiDemos/src/com/example/android/apis/view/CustomLayout.java b/samples/ApiDemos/src/com/example/android/apis/view/CustomLayout.java new file mode 100644 index 000000000..dfd886a60 --- /dev/null +++ b/samples/ApiDemos/src/com/example/android/apis/view/CustomLayout.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.apis.view; + +// Need the following import to get access to the app resources, since this +// class is in a sub-package. +import android.graphics.Rect; +import com.example.android.apis.R; + +//BEGIN_INCLUDE(Complete) +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RemoteViews; + +/** + * Example of writing a custom layout manager. This is a fairly full-featured + * layout manager that is relatively general, handling all layout cases. You + * can simplify it for more specific cases. + */ +@RemoteViews.RemoteView +public class CustomLayout extends ViewGroup { + /** The amount of space used by children in the left gutter. */ + private int mLeftWidth; + + /** The amount of space used by children in the right gutter. */ + private int mRightWidth; + + /** These are used for computing child frames based on their gravity. */ + private final Rect mTmpContainerRect = new Rect(); + private final Rect mTmpChildRect = new Rect(); + + public CustomLayout(Context context) { + super(context); + } + + public CustomLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CustomLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * Any layout manager that doesn't scroll will want this. + */ + @Override + public boolean shouldDelayChildPressedState() { + return false; + } + + /** + * Ask all children to measure themselves and compute the measurement of this + * layout based on the children. + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int count = getChildCount(); + + // These keep track of the space we are using on the left and right for + // views positioned there; we need member variables so we can also use + // these for layout later. + mLeftWidth = 0; + mRightWidth = 0; + + // Measurement will ultimately be computing these values. + int maxHeight = 0; + int maxWidth = 0; + int childState = 0; + + // Iterate through all children, measuring them and computing our dimensions + // from their size. + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + // Measure the child. + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + + // Update our size information based on the layout params. Children + // that asked to be positioned on the left or right go in those gutters. + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp.position == LayoutParams.POSITION_LEFT) { + mLeftWidth += Math.max(maxWidth, + child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); + } else if (lp.position == LayoutParams.POSITION_RIGHT) { + mRightWidth += Math.max(maxWidth, + child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); + } else { + maxWidth = Math.max(maxWidth, + child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); + } + maxHeight = Math.max(maxHeight, + child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin); + childState = combineMeasuredStates(childState, child.getMeasuredState()); + } + } + + // Total width is the maximum width of all inner children plus the gutters. + maxWidth += mLeftWidth + mRightWidth; + + // Check against our minimum height and width + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); + + // Report our final dimensions. + setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), + resolveSizeAndState(maxHeight, heightMeasureSpec, + childState << MEASURED_HEIGHT_STATE_SHIFT)); + } + + /** + * Position all children within this layout. + */ + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + final int count = getChildCount(); + + // These are the far left and right edges in which we are performing layout. + int leftPos = getPaddingLeft(); + int rightPos = right - left - getPaddingRight(); + + // This is the middle region inside of the gutter. + final int middleLeft = leftPos + mLeftWidth; + final int middleRight = rightPos - mRightWidth; + + // These are the top and bottom edges in which we are performing layout. + final int parentTop = getPaddingTop(); + final int parentBottom = bottom - top - getPaddingBottom(); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + final int width = child.getMeasuredWidth(); + final int height = child.getMeasuredHeight(); + + // Compute the frame in which we are placing this child. + if (lp.position == LayoutParams.POSITION_LEFT) { + mTmpContainerRect.left = leftPos + lp.leftMargin; + mTmpContainerRect.right = leftPos + width + lp.rightMargin; + leftPos = mTmpContainerRect.right; + } else if (lp.position == LayoutParams.POSITION_RIGHT) { + mTmpContainerRect.right = rightPos - lp.rightMargin; + mTmpContainerRect.left = rightPos - width - lp.leftMargin; + rightPos = mTmpContainerRect.left; + } else { + mTmpContainerRect.left = middleLeft + lp.leftMargin; + mTmpContainerRect.right = middleRight - lp.rightMargin; + } + mTmpContainerRect.top = parentTop + lp.topMargin; + mTmpContainerRect.bottom = parentBottom - lp.bottomMargin; + + // Use the child's gravity and size to determine its final + // frame within its container. + Gravity.apply(lp.gravity, width, height, mTmpContainerRect, mTmpChildRect); + + // Place the child. + child.layout(mTmpChildRect.left, mTmpChildRect.top, + mTmpChildRect.right, mTmpChildRect.bottom); + } + } + } + + // ---------------------------------------------------------------------- + // The rest of the implementation is for custom per-child layout parameters. + // If you do not need these (for example you are writing a layout manager + // that does fixed positioning of its children), you can drop all of this. + + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return new CustomLayout.LayoutParams(getContext(), attrs); + } + + @Override + protected LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return new LayoutParams(p); + } + + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams; + } + + /** + * Custom per-child layout information. + */ + public static class LayoutParams extends MarginLayoutParams { + /** + * The gravity to apply with the View to which these layout parameters + * are associated. + */ + public int gravity = Gravity.TOP | Gravity.START; + + public static int POSITION_MIDDLE = 0; + public static int POSITION_LEFT = 1; + public static int POSITION_RIGHT = 2; + + public int position = POSITION_MIDDLE; + + public LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + + // Pull the layout param values from the layout XML during + // inflation. This is not needed if you don't care about + // changing the layout behavior in XML. + TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.CustomLayoutLP); + gravity = a.getInt(R.styleable.CustomLayoutLP_android_layout_gravity, gravity); + position = a.getInt(R.styleable.CustomLayoutLP_layout_position, position); + a.recycle(); + } + + public LayoutParams(int width, int height) { + super(width, height); + } + + public LayoutParams(ViewGroup.LayoutParams source) { + super(source); + } + } +} +//END_INCLUDE(Complete) diff --git a/samples/ApiDemos/src/com/example/android/apis/view/CustomLayoutActivity.java b/samples/ApiDemos/src/com/example/android/apis/view/CustomLayoutActivity.java new file mode 100644 index 000000000..171656933 --- /dev/null +++ b/samples/ApiDemos/src/com/example/android/apis/view/CustomLayoutActivity.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.apis.view; + +// Need the following import to get access to the app resources, since this +// class is in a sub-package. +import com.example.android.apis.R; + +import android.app.Activity; +import android.os.Bundle; + +public class CustomLayoutActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.custom_layout); + } +} |