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

Reply via email to