Reputation: 43504
I have a problem when my strings in my TextView
s grow and overflows, sometimes hiding the text of another TextView
or starting to disappear.
I would like it to work like this (I know this looks a lot like swings FlowLayout
but not quite since it's alignment isn't fixed, one component is left and the other right aligned):
-------------------------------------
|[TextView0] [TextView1]|
-------------------------------------
And when the text grows:
TextView0 grows: TextView1 grows:
------------------------------------- -------------------------------------
|[TextView0 TextView0 TextView0] | |[TextView0] |
| [TextView1]| | [TextView1 TextView1 TextView1]|
------------------------------------- -------------------------------------
I have tried ReleativeLayout
and LinearLayout
but never got it to work:
RelativeLayout
:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/TextView0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="TextView0" />
<TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="TextView1" />
</RelativeLayout>
When the text the start to overlap which I tried to fix with TextView0
being toLeftOf="TextView1"
. But in that case TextView0
disappears.
LinearLayout
:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/TextView0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView0" />
<TextView
android:id="@+id/TextView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:text="TextView1" />
</LinearLayout>
Here the TextView
s start to interfere and when TextView0
gets the full width TextView1
disappears (its width goes towards zero).
Upvotes: 1
Views: 2911
Reputation: 43504
I made an attempt to create a layout for this purpose.
It works like I discuss in the original question but feel free to update the answer if you make it better!
public class KeyValueLayout extends ViewGroup {
public KeyValueLayout(Context context) {
super(context);
}
public KeyValueLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public KeyValueLayout(Context context, AttributeSet attributeSet,
int defStyle) {
super(context, attributeSet, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int paddRight = getPaddingRight();
int paddLeft = getPaddingLeft();
int paddBottom = getPaddingBottom();
int paddWidth = paddRight + paddLeft;
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec) - paddWidth;
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec) - paddWidth;
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int modeW = modeWidth == MeasureSpec.EXACTLY
? MeasureSpec.AT_MOST : modeWidth;
int modeH = modeHeight == MeasureSpec.EXACTLY
? MeasureSpec.AT_MOST : modeHeight;
// where the next view should be placed
int lineYPosition = 0;
for (int i = 0; i < getChildCount(); ) {
View key = getChildAt(i++);
key.measure(
MeasureSpec.makeMeasureSpec(sizeWidth, modeW),
MeasureSpec.makeMeasureSpec(sizeHeight, modeH)
);
LayoutParams keyLp = (LayoutParams) key.getLayoutParams();
keyLp.setPosition(paddLeft, lineYPosition);
if (i >= getChildCount())
break;
View val = getChildAt(i++);
val.measure(
MeasureSpec.makeMeasureSpec(sizeWidth, modeW),
MeasureSpec.makeMeasureSpec(sizeHeight, modeH)
);
LayoutParams valLp = (LayoutParams) val.getLayoutParams();
int valXPosition = paddLeft + sizeWidth - val.getMeasuredWidth();
// check if both fit on the same line
if (key.getMeasuredWidth() + val.getMeasuredWidth() <= sizeWidth) {
valLp.setPosition(valXPosition, lineYPosition);
lineYPosition += Math.max(key.getMeasuredHeight(),
val.getMeasuredHeight());
} else {
// not enough room, make some space
lineYPosition += key.getMeasuredHeight();
valLp.setPosition(valXPosition, lineYPosition);
lineYPosition += val.getMeasuredHeight();
}
}
int controlMaxLength = sizeWidth + paddRight;
int controlMaxThickness = lineYPosition + paddBottom;
int resolvedWidth = resolveSize(controlMaxLength, widthMeasureSpec);
int resolvedHeight =resolveSize(controlMaxThickness,heightMeasureSpec);
this.setMeasuredDimension(resolvedWidth, resolvedHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
child.layout(lp.x, lp.y,
lp.x + child.getMeasuredWidth(),
lp.y + child.getMeasuredHeight());
}
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attributeSet) {
return new LayoutParams(getContext(), attributeSet);
}
@Override
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
public static class LayoutParams extends ViewGroup.LayoutParams {
private int x;
private int y;
public LayoutParams(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(ViewGroup.LayoutParams layoutParams) {
super(layoutParams);
}
public void setPosition(int x, int y) {
this.x = x;
this.y = y;
}
}
}
Example usage:
<nu.wen.android.layout.KeyValueLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/example_string_long"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/example_string_short" />
</nu.wen.android.layout.KeyValueLayout>
Upvotes: 0
Reputation: 8734
One of the best lib for that Android-FlowLayout
its simple, easy to use and awesome.
Upvotes: 1
Reputation: 2674
The short answer is "yes" - because it is just software, anything can be done :). However, I don't think you can achieve it with any standard layout.
So my best bet is that you create your own View class and then layout things in whatever way you want. You may want to read this (if you have not) as a starting point:
http://developer.android.com/training/custom-views/create-view.html
Upvotes: 0