android - Is it possible to implement a FlowLayout with RelativeLayout properties? -
i create custom relativelayout has 2 views in 1 row: 1 on left side of screen (android:layout_alignparentstart="true") , 1 on right (android:layout_alignparentend="true"). view on right grow toward left view until takes space between 2 views. move new line under view on left.
i have implemented modified version of romain guy's flowlayout extends relativelayout. however, class seems ignore relativelayout's align properties , sticks views right next each other. there way implement such layout anchor views left , right?
flowlayout class:
public class flowlayout extends relativelayout { private int mhorizontalspacing; private int mverticalspacing; public flowlayout(context context) { super(context); } public flowlayout(context context, attributeset attrs) { super(context, attrs); typedarray attributes = context.obtainstyledattributes(attrs, r.styleable.flowlayout); mhorizontalspacing = attributes.getdimensionpixelsize(r.styleable .flowlayout_horizontalspacing, 0); mverticalspacing = attributes.getdimensionpixelsize(r.styleable .flowlayout_verticalspacing, 0); attributes.recycle(); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { int widthsize = measurespec.getsize(widthmeasurespec); int width = 0; int height = getpaddingtop(); int currentwidth = getpaddingstart(); int currentheight = 0; final int count = getchildcount(); (int = 0; < count; i++) { view child = getchildat(i); layoutparams lp = (layoutparams) child.getlayoutparams(); measurechild(child, widthmeasurespec, heightmeasurespec); if (currentwidth + child.getmeasuredwidth() > widthsize) { height += currentheight + mverticalspacing; currentheight = 0; width = math.max(width, currentwidth); currentwidth = getpaddingend(); } int spacing = mhorizontalspacing; if (lp.spacing > -1) { spacing = lp.spacing; } lp.x = currentwidth + spacing; lp.y = currentheight; currentwidth += child.getmeasuredwidth(); currentheight = math.max(currentheight, child.getmeasuredheight()); } width += getpaddingend(); height += getpaddingbottom(); setmeasureddimension(resolvesize(width, widthmeasurespec), resolvesize(height, heightmeasurespec)); } @override protected void onlayout(boolean changed, int l, int t, int r, int b) { final int count = getchildcount(); (int = 0; < 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 viewgroup.layoutparams generatedefaultlayoutparams() { return new layoutparams(relativelayout.layoutparams.wrap_content, relativelayout .layoutparams.wrap_content); } @override protected viewgroup.layoutparams generatelayoutparams(viewgroup.layoutparams p) { return new layoutparams(p.width, p.height); } @override public relativelayout.layoutparams generatelayoutparams(attributeset attrs) { return new layoutparams(getcontext(), attrs); } public static class layoutparams extends relativelayout.layoutparams { public int spacing; public int x; public int y; public layoutparams(context context, attributeset attrs) { super(context, attrs); typedarray attributes = context.obtainstyledattributes(attrs, r.styleable .flowlayout_layoutparams); spacing = attributes.getdimensionpixelsize(r.styleable .flowlayout_layoutparams_layoutspacing, -1); attributes.recycle(); } public layoutparams(int width, int height) { super(width, height); } } }
it turns out rather calculating right view's new position yourself, can change layoutparams , have os handle positioning you. created custom layout extends relativelayout , overrides onmeasure() method. adjust layoutparams accordingly.
more specifically: call super method find widths of 2 views , parent in onmeasure()
. use these figure out if right view overlap left view. if so, change right view's layout_alignparentend="true"
property layout_alignparentstart="true"
, give layout_below="@id/left_view"
property. opposite when there no overlap. call super method again have os remeasure views you.
the layout class:
public class wrappinglayout extends relativelayout { private textview leftview; private edittext rightview; //use prevent unnecessarily adjusting layoutparams //when right view in correct position private boolean ismultiline = false; public wrappinglayout(context context) { super(context); layoutinflater inflater = layoutinflater.from(context); inflater.inflate(r.layout.wrapping_layout, this); leftview = (textview) findviewbyid(r.id.left_view); rightview = (edittext) findviewbyid(r.id.right_view); } public wrappinglayout(context context, attributeset attrs) { super(context, attrs); layoutinflater inflater = layoutinflater.from(context); inflater.inflate(r.layout.wrapping_layout, this); leftview = (textview) findviewbyid(r.id.left_view); rightview = (edittext) findviewbyid(r.id.right_view); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { //call first make sure views' initial widths have been set super.onmeasure(widthmeasurespec, heightmeasurespec); int screenwidth = getmeasuredwidth(); int leftviewwidth = getpaddingstart() + leftview.getmeasuredwidth() + leftview.getpaddingend(); int rightviewwidth = getpaddingend() + rightview.getmeasuredwidth() + rightview.getpaddingstart(); layoutparams rightviewparams = (layoutparams) rightview.getlayoutparams(); if (!ismultiline && rightviewwidth + leftviewwidth > screenwidth) { ismultiline = true; rightviewparams.addrule(below, r.id.left_view); rightviewparams.removerule(align_parent_end); rightviewparams.addrule(align_parent_start); //call again here adjust dimensions new params super.onmeasure(widthmeasurespec, heightmeasurespec); } else if (ismultiline && rightviewwidth + leftviewwidth < screenwidth) { ismultiline = false; rightviewparams.removerule(below); rightviewparams.addrule(align_parent_end); rightviewparams.removerule(align_parent_start); //call again here adjust dimensions new params super.onmeasure(widthmeasurespec, heightmeasurespec); } } }
the layout xml:
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <textview android:id="@id/left_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentstart="true" android:layout_centervertical="true"/> <edittext android:id="@id/right_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentend="true" android:gravity="center" android:text="@string/hello"/> </merge>
Comments
Post a Comment