Aligining fields in the editor
Change-Id: I7137055bf8ab61df33f6a87c8e6c8227dbee8a9f
diff --git a/res/layout-xlarge/item_group_membership.xml b/res/layout-xlarge/item_group_membership.xml
index c5f0dcf..1b47b9e 100644
--- a/res/layout-xlarge/item_group_membership.xml
+++ b/res/layout-xlarge/item_group_membership.xml
@@ -19,21 +19,22 @@
<com.android.contacts.editor.GroupMembershipView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeight"
+ android:layout_height="@dimen/editor_min_line_item_height"
android:orientation="horizontal">
<TextView
android:id="@+id/kind_title"
android:layout_width="150dip"
- android:layout_height="wrap_content"
+ android:layout_height="@dimen/editor_min_line_item_height"
+ android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceSmall"
android:singleLine="true"
android:textColor="@color/editor_label_text_color"
android:ellipsize="marquee" />
+ <!-- TODO: Change to android.R.attr.spinnerTextStyle when available-->
<TextView
- style="?android:attr/dropDownSpinnerStyle"
+ style="?android:attr/editTextStyle"
android:id="@+id/group_list"
android:layout_width="0dip"
android:layout_height="wrap_content"
@@ -43,7 +44,7 @@
android:ellipsize="end"
android:focusable="true"
/>
-
+
<!-- Plus/Minus button only for layout. This makes the editor lay out nicely with the other fields -->
<ImageButton
android:layout_width="wrap_content"
diff --git a/res/layout-xlarge/item_kind_section.xml b/res/layout-xlarge/item_kind_section.xml
index 0d44af6..57de26d 100644
--- a/res/layout-xlarge/item_kind_section.xml
+++ b/res/layout-xlarge/item_kind_section.xml
@@ -25,7 +25,8 @@
<TextView
android:id="@+id/kind_title"
android:layout_width="150dip"
- android:layout_height="wrap_content"
+ android:layout_height="@dimen/editor_min_line_item_height"
+ android:gravity="center_vertical"
android:textColor="#7F7F7F"
android:textAppearance="?android:attr/textAppearanceSmall"
android:singleLine="true"
@@ -39,16 +40,21 @@
android:layout_gravity="bottom"
android:orientation="vertical" />
- <ImageButton
- android:id="@+id/kind_plus"
+ <FrameLayout
+ android:id="@+id/kind_plus_container"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"
- android:paddingLeft="@dimen/editor_round_button_padding_left"
- android:paddingRight="@dimen/editor_round_button_padding_right"
- android:paddingTop="@dimen/editor_round_button_padding_top"
- android:paddingBottom="@dimen/editor_round_button_padding_bottom"
- android:background="?android:attr/selectableItemBackground"
- android:src="@drawable/ic_menu_add_field_holo_light"
- android:contentDescription="@string/description_plus_button" />
+ android:layout_height="@dimen/editor_min_line_item_height">
+ <ImageButton
+ android:id="@+id/kind_plus"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingLeft="@dimen/editor_round_button_padding_left"
+ android:paddingRight="@dimen/editor_round_button_padding_right"
+ android:paddingTop="@dimen/editor_round_button_padding_top"
+ android:paddingBottom="@dimen/editor_round_button_padding_bottom"
+ android:background="?android:attr/selectableItemBackground"
+ android:src="@drawable/ic_menu_add_field_holo_light"
+ android:contentDescription="@string/description_plus_button" />
+ </FrameLayout>
</com.android.contacts.editor.KindSectionView>
diff --git a/res/layout-xlarge/raw_contact_editor_view.xml b/res/layout-xlarge/raw_contact_editor_view.xml
index 07731fc..3560fa6 100644
--- a/res/layout-xlarge/raw_contact_editor_view.xml
+++ b/res/layout-xlarge/raw_contact_editor_view.xml
@@ -82,7 +82,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
- android:layout_marginBottom="10dip">>
+ android:layout_marginBottom="42dip">
<Button
android:id="@+id/button_add_field"
android:text="@string/add_field"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 0916989..5f01cbd 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -38,11 +38,14 @@
<dimen name="quick_contact_width">352dip</dimen>
<!-- Padding of the rounded plus/minus/expand/collapse buttons in the editor -->
- <dimen name="editor_round_button_padding_left">10dip</dimen>
- <dimen name="editor_round_button_padding_right">10dip</dimen>
- <dimen name="editor_round_button_padding_top">10dip</dimen>
- <dimen name="editor_round_button_padding_bottom">10dip</dimen>
+ <dimen name="editor_round_button_padding_left">8dip</dimen>
+ <dimen name="editor_round_button_padding_right">8dip</dimen>
+ <dimen name="editor_round_button_padding_top">8dip</dimen>
+ <dimen name="editor_round_button_padding_bottom">8dip</dimen>
<!-- Width of the Type-Label in the Editor -->
<dimen name="editor_type_label_width">180dip</dimen>
+
+ <!-- Minimum height of a row in the Editor -->
+ <dimen name="editor_min_line_item_height">48dip</dimen>
</resources>
diff --git a/src/com/android/contacts/editor/EventFieldEditorView.java b/src/com/android/contacts/editor/EventFieldEditorView.java
index 1d2ccdc..c386812 100644
--- a/src/com/android/contacts/editor/EventFieldEditorView.java
+++ b/src/com/android/contacts/editor/EventFieldEditorView.java
@@ -64,6 +64,18 @@
}
@Override
+ public int getBaseline(int row) {
+ int baseline = super.getBaseline(row);
+ if (mDateView != null) {
+ // The date view will be centered vertically in the corresponding line item
+ int lineItemHeight = getLineItemHeight(row);
+ int offset = (lineItemHeight - mDateView.getMeasuredHeight()) / 2;
+ baseline = Math.max(baseline, offset + mDateView.getBaseline());
+ }
+ return baseline;
+ }
+
+ @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
@@ -76,12 +88,20 @@
final int labelWidth = (getLabel() != null) ? getLabel().getMeasuredWidth() : 0;
final int deleteWidth = (getDelete() != null) ? getDelete().getMeasuredWidth() : 0;
final int r2 = r1 - deleteWidth - labelWidth;
- if (mDateView != null) mDateView.layout(l1, t1, r2, t1 + mDateView.getMeasuredHeight());
+ if (mDateView != null) {
+ int height = mDateView.getMeasuredHeight();
+ int baseline = getBaseline(0);
+ int top = t1 + baseline - mDateView.getBaseline();
+ mDateView.layout(
+ l1, top,
+ r2, top + height);
+ }
}
@Override
- protected int getEditorHeight() {
- return mDateView != null ? mDateView.getMeasuredHeight() : 0;
+ protected int getLineItemHeight(int row) {
+ int height = mDateView == null ? 0 : mDateView.getMeasuredHeight();
+ return Math.max(height, super.getLineItemHeight(row));
}
@Override
@@ -103,7 +123,9 @@
super.setValues(kind, entry, state, readOnly, vig);
if (mDateView == null) {
- mDateView = new TextView(getContext(), null, android.R.attr.dropDownSpinnerStyle);
+
+ // TODO: Change to android.R.attr.spinnerTextStyle when available
+ mDateView = new TextView(getContext(), null, android.R.attr.editTextStyle);
mDateView.setFocusable(true);
mDateView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
diff --git a/src/com/android/contacts/editor/KindSectionView.java b/src/com/android/contacts/editor/KindSectionView.java
index 0ece15a..1debaa2 100644
--- a/src/com/android/contacts/editor/KindSectionView.java
+++ b/src/com/android/contacts/editor/KindSectionView.java
@@ -43,6 +43,7 @@
private static final String TAG = "KindSectionView";
private ViewGroup mEditors;
+ private View mAddPlusButtonContainer;
private ImageButton mAddPlusButton;
private TextView mTitle;
private String mTitleString;
@@ -53,12 +54,16 @@
private ViewIdGenerator mViewIdGenerator;
+ private int mMinLineItemHeight;
+
public KindSectionView(Context context) {
- super(context);
+ this(context, null);
}
public KindSectionView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mMinLineItemHeight = context.getResources().getDimensionPixelSize(
+ R.dimen.editor_min_line_item_height);
}
@Override
@@ -76,6 +81,24 @@
}
}
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ if (!changed) {
+ return;
+ }
+
+ if (mAddPlusButton == null || mEditors == null || mEditors.getChildCount() < 2) {
+ return;
+ }
+
+ // Align the "+" button with the "-" button in the last editor
+ View lastEditor = mEditors.getChildAt(mEditors.getChildCount() - 1);
+ int top = lastEditor.getTop();
+ mAddPlusButtonContainer.layout(mAddPlusButtonContainer.getLeft(), top,
+ mAddPlusButtonContainer.getRight(), top + mAddPlusButtonContainer.getHeight());
+ }
+
public boolean isReadOnly() {
return mReadOnly;
}
@@ -88,6 +111,7 @@
mEditors = (ViewGroup)findViewById(R.id.kind_editors);
+ mAddPlusButtonContainer = findViewById(R.id.kind_plus_container);
mAddPlusButton = (ImageButton) findViewById(R.id.kind_plus);
mAddPlusButton.setOnClickListener(new OnClickListener() {
@Override
diff --git a/src/com/android/contacts/editor/LabeledEditorView.java b/src/com/android/contacts/editor/LabeledEditorView.java
index f06191a..6d44d15 100644
--- a/src/com/android/contacts/editor/LabeledEditorView.java
+++ b/src/com/android/contacts/editor/LabeledEditorView.java
@@ -76,6 +76,7 @@
private ViewIdGenerator mViewIdGenerator;
private DialogManager mDialogManager = null;
private EditorListener mListener;
+ protected int mMinLineItemHeight;
/**
* A marker in the spinner adapter of the currently selected custom type.
@@ -97,20 +98,82 @@
public LabeledEditorView(Context context) {
super(context);
+ init(context);
}
public LabeledEditorView(Context context, AttributeSet attrs) {
super(context, attrs);
+ init(context);
}
public LabeledEditorView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ init(context);
+ }
+
+ private void init(Context context) {
+ mMinLineItemHeight = context.getResources().getDimensionPixelSize(
+ R.dimen.editor_min_line_item_height);
}
public boolean isReadOnly() {
return mReadOnly;
}
+ public int getBaseline(int row) {
+ if (row == 0 && mLabel != null) {
+ return mLabel.getBaseline();
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the number of rows in this editor, including the invisible ones.
+ */
+ protected int getLineItemCount() {
+ return 1;
+ }
+
+ protected boolean isLineItemVisible(int row) {
+ return true;
+ }
+
+ protected int getLineItemHeight(int row) {
+ int fieldHeight = 0;
+ int buttonHeight = 0;
+ if (row == 0) {
+ // summarize the EditText heights
+ if (mLabel != null) {
+ fieldHeight = mLabel.getMeasuredHeight();
+ }
+
+ // Ensure there is enough space for the minus button
+ View deleteButton = getDelete();
+ final int deleteHeight = (deleteButton != null) ? deleteButton.getMeasuredHeight() : 0;
+ buttonHeight += deleteHeight;
+ }
+
+ return Math.max(Math.max(buttonHeight, fieldHeight), mMinLineItemHeight);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ measureChildren(widthMeasureSpec, heightMeasureSpec);
+
+ int height = 0;
+ height += getPaddingTop() + getPaddingBottom();
+
+ int count = getLineItemCount();
+ for (int i = 0; i < count; i++) {
+ if (isLineItemVisible(i)) {
+ height += getLineItemHeight(i);
+ }
+ }
+
+ setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
+ resolveSize(height, heightMeasureSpec));
+ }
+
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// Subtract padding from the borders ==> x1 variables
@@ -121,38 +184,25 @@
final int r2;
if (mDelete != null) {
r2 = r1 - mDelete.getMeasuredWidth();
+ // Vertically center the delete button in the first line item
+ int height = mDelete.getMeasuredHeight();
+ int top = t1 + (mMinLineItemHeight - height) / 2;
mDelete.layout(
- r2, b1 - mDelete.getMeasuredHeight(),
- r1, b1);
+ r2, top,
+ r1, top + height);
} else {
r2 = r1;
}
if (mLabel != null) {
+ int baseline = getBaseline(0);
+ int y = t1 + baseline - mLabel.getBaseline();
mLabel.layout(
- r2 - mLabel.getMeasuredWidth(), t1,
- r2, t1 + mLabel.getMeasuredHeight());
+ r2 - mLabel.getMeasuredWidth(), y,
+ r2, y + mLabel.getMeasuredHeight());
}
-
}
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- measureChildren(widthMeasureSpec, heightMeasureSpec);
-
- final int padding = getPaddingTop() + getPaddingBottom();
- final int deleteHeight = mDelete != null ? mDelete.getMeasuredHeight() : 0;
- final int labelHeight = mLabel != null ? mLabel.getMeasuredHeight() : 0;
-
- final int height = padding +
- Math.max(Math.max(deleteHeight, labelHeight), getEditorHeight());
-
- setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
- resolveSize(height, heightMeasureSpec));
- }
-
- protected abstract int getEditorHeight();
-
/**
* Creates or removes the type/label button. Doesn't do anything if already correctly configured
*/
diff --git a/src/com/android/contacts/editor/TextFieldsEditorView.java b/src/com/android/contacts/editor/TextFieldsEditorView.java
index 7096a79..516ae1c 100644
--- a/src/com/android/contacts/editor/TextFieldsEditorView.java
+++ b/src/com/android/contacts/editor/TextFieldsEditorView.java
@@ -65,6 +65,30 @@
}
@Override
+ protected int getLineItemCount() {
+ int count = mFieldEditTexts == null ? 0 : mFieldEditTexts.length;
+ return Math.max(count, super.getLineItemCount());
+ }
+
+ @Override
+ protected boolean isLineItemVisible(int row) {
+ return mFieldEditTexts != null && mFieldEditTexts[row].getVisibility() != View.GONE;
+ }
+
+ @Override
+ public int getBaseline(int row) {
+ int baseline = super.getBaseline(row);
+ if (mFieldEditTexts != null) {
+ EditText editText = mFieldEditTexts[row];
+ // The text field will be centered vertically in the corresponding line item
+ int lineItemHeight = getLineItemHeight(row);
+ int offset = (lineItemHeight - editText.getMeasuredHeight()) / 2;
+ baseline = Math.max(baseline, offset + editText.getBaseline());
+ }
+ return baseline;
+ }
+
+ @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
@@ -87,34 +111,46 @@
// Layout text fields
int y = t1;
if (mFieldEditTexts != null) {
- for (EditText editText : mFieldEditTexts) {
+ for (int i = 0; i < mFieldEditTexts.length; i++) {
+ int baseline = getBaseline(i);
+ EditText editText = mFieldEditTexts[i];
if (editText.getVisibility() != View.GONE) {
int height = editText.getMeasuredHeight();
+ int top = t1 + y + baseline - editText.getBaseline();
editText.layout(
- l1, t1 + y,
- r2, t1 + y + height);
- y += height;
+ l1, top,
+ r2, top + height);
+ y += getLineItemHeight(i);
}
}
}
}
@Override
- protected int getEditorHeight() {
- int result = 0;
- // summarize the EditText heights
+ protected int getLineItemHeight(int row) {
+ int fieldHeight = 0;
+ int buttonHeight = 0;
+
+ boolean lastLineItem = true;
if (mFieldEditTexts != null) {
- for (EditText editText : mFieldEditTexts) {
- if (editText.getVisibility() != View.GONE) {
- result += editText.getMeasuredHeight();
- }
- }
+ fieldHeight = mFieldEditTexts[row].getMeasuredHeight();
+ lastLineItem = (row == mFieldEditTexts.length - 1);
}
- // Ensure there is enough space for the minus and more/less button
- final int deleteHeight = (getDelete() != null) ? getDelete().getMeasuredHeight() : 0;
- final int moreOrLessHeight = mMoreOrLess != null ? mMoreOrLess.getMeasuredHeight() : 0;
- result = Math.max(deleteHeight + moreOrLessHeight, result);
- return result;
+
+ // Ensure there is enough space for the more/less button
+ if (row == 0) {
+ final int moreOrLessHeight = mMoreOrLess != null ? mMoreOrLess.getMeasuredHeight() : 0;
+ buttonHeight += moreOrLessHeight;
+ }
+
+ // Ensure there is enough space for the minus button
+ if (lastLineItem) {
+ View deleteButton = getDelete();
+ final int deleteHeight = (deleteButton != null) ? deleteButton.getMeasuredHeight() : 0;
+ buttonHeight += deleteHeight;
+ }
+
+ return Math.max(Math.max(buttonHeight, fieldHeight), super.getLineItemHeight(row));
}
@Override
diff --git a/src/com/android/contacts/util/ThemeUtils.java b/src/com/android/contacts/util/ThemeUtils.java
index f2d84dd..276de29 100644
--- a/src/com/android/contacts/util/ThemeUtils.java
+++ b/src/com/android/contacts/util/ThemeUtils.java
@@ -8,7 +8,7 @@
*/
public class ThemeUtils {
/**
- * Resolves the given attribute id of the theme to a ressource id
+ * Resolves the given attribute id of the theme to a resource id
*/
public static int getAttribute(Theme theme, int attrId) {
final TypedValue outValue = new TypedValue();
@@ -17,7 +17,7 @@
}
/**
- * Returns the ressource id of the background used for buttons to show pressed and focused state
+ * Returns the resource id of the background used for buttons to show pressed and focused state
*/
public static int getSelectableItemBackground(Theme theme) {
return getAttribute(theme, android.R.attr.selectableItemBackground);