I bit the bullet and wrote a class: WritingLayout is a ViewGroup which lays
out children horizontally to a given width, then begins a new line.
Warning: It's a proof-of-concept. You may wish to tighten it up, and
perhaps add some bells and whistles.
package com.downacross.util;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
/**
* Left-to-right, then top-to-bottom, layout.
*
* This layout positions its components similarly to writing text on a
(Western) page.
* It goes left to right up to a given width, then wraps to the start of
the next line down, and continues.
* The children get as much space as they ask for.
*
* This layout does not know about justification, and does not put space
between children.
*
* WARNING: This is not a complete, robust class. For example, there's no
concurrency protection.
* Also, more methods should be overridden, especially the other addView
methods.
*/
public class WritingLayout extends ViewGroup {
/**
* Holds all component views, in order.
*/
private final ArrayList<View> childViews = new ArrayList<View>() ;
/**
* Holds layout bounds for corresponding child views. This is set in {@link
#onMeasure}, and used in {@link #onLayout}.
*/
private final ArrayList<Rect> childPositions = new ArrayList<Rect>() ;
public WritingLayout(Context context) {
super(context);
}
/**
* Adds a child view to the end of the list of children. Currently 31jan12,
this is the only addView method that should be called.
*/
@Override
public void addView(View child) {
super.addView(child); // Necessary for event propagation, perhaps other
framework stuff.
childViews.add(child);
childPositions.add(new Rect());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
////// Extract incoming constraints
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); // This is our
line-length limit.
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
////// Measure child views
int childWidthMode = widthMode == MeasureSpec.EXACTLY ? MeasureSpec.AT_MOST
: widthMode ;
int childHeightMode = heightMode == MeasureSpec.EXACTLY ?
MeasureSpec.AT_MOST : heightMode ;
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthMode,
widthMode);
int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightMode,
heightMode);
for (View childView : childViews) {
childView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
////// Position each child
int acrossPosition = 0 ; // Rightmost edge of last view on this line.
int lineTop = 0 ; // Bottom edge of previous line.
int lineHeight = 0 ; // Bottom edge of this line, so far.
int childCount = childViews.size();
for (int i=0 ; i<childCount ; i++) {
////// Get required info
View childView = childViews.get(i);
Rect childPosition = childPositions.get(i);
int childWidth = childView.getMeasuredWidth();
int childHeight = childView.getMeasuredHeight();
////// Perhaps start new line
if (acrossPosition + childWidth > widthSpecSize) {
// Have filled line, start a new one.
acrossPosition = 0 ;
lineTop += lineHeight ;
lineHeight = 0 ;
}
////// Place this child, and update progress variables.
int right = acrossPosition + childWidth ;
childPosition.set(acrossPosition, lineTop, right, lineTop+childHeight);
acrossPosition = right ;
if (childHeight>lineHeight) lineHeight = childHeight ;
}
////// Set the WritingLayout's measurements.
int pageHeight = lineTop + lineHeight ;
this.setMeasuredDimension(widthSpecSize, pageHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// Don't know exactly what the 'changed' argument means.
int childCount = childViews.size();
for (int i=0 ; i<childCount ; i++) {
View childView = childViews.get(i);
Rect childPosition = childPositions.get(i);
childView.layout(childPosition.left, childPosition.top,
childPosition.right, childPosition.bottom);
}
}
}
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en