android - Resizing rotated child view in custom ViewGroup subclass -
background
i have custom viewgroup
subclass rotates , mirrors child view. purpose correctly display traditional mongolian text.
i put viewgroup
, current project putting edittext
in it. (i never successful in rotating , mirroring edittext
directly. however, wrapping in custom view group work.)
problem
my problem when try resize viewgroup
programmatically, child view not getting resized along it. edittext
match size of parent viewgroup
appears single view.
i made new project show problem. button increases width of viewgroup (shown in red). images show project start (with working fine) , 2 width increments. edittext
white , not getting resized though width , height set match_parent
the full project code below.
mongolviewgroup.java (custom viewgroup rotates , mirrors content)
public class mongolviewgroup extends viewgroup { private int angle = 90; private final matrix rotatematrix = new matrix(); private final rect viewrectrotated = new rect(); private final rectf temprectf1 = new rectf(); private final rectf temprectf2 = new rectf(); private final float[] viewtouchpoint = new float[2]; private final float[] childtouchpoint = new float[2]; private boolean anglechanged = true; public mongolviewgroup(context context) { this(context, null); } public mongolviewgroup(context context, attributeset attrs) { super(context, attrs); setwillnotdraw(false); } public view getview() { return getchildat(0); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { final view view = getview(); if (view != null) { measurechild(view, heightmeasurespec, widthmeasurespec); setmeasureddimension(resolvesize(view.getmeasuredheight(), widthmeasurespec), resolvesize(view.getmeasuredwidth(), heightmeasurespec)); } else { super.onmeasure(widthmeasurespec, heightmeasurespec); } } @override protected void onlayout(boolean changed, int left, int top, int right, int bottom) { if (anglechanged) { final rectf layoutrect = temprectf1; final rectf layoutrectrotated = temprectf2; layoutrect.set(0, 0, right - left, bottom - top); rotatematrix.setrotate(angle, layoutrect.centerx(), layoutrect.centery()); rotatematrix.postscale(-1, 1); rotatematrix.maprect(layoutrectrotated, layoutrect); layoutrectrotated.round(viewrectrotated); anglechanged = false; } final view view = getview(); if (view != null) { view.layout(viewrectrotated.left, viewrectrotated.top, viewrectrotated.right, viewrectrotated.bottom); } } @override protected void dispatchdraw(canvas canvas) { canvas.save(); canvas.rotate(-angle, getwidth() / 2f, getheight() / 2f); canvas.scale(-1, 1); super.dispatchdraw(canvas); canvas.restore(); } @override public viewparent invalidatechildinparent(int[] location, rect dirty) { invalidate(); return super.invalidatechildinparent(location, dirty); } @override public boolean dispatchtouchevent(motionevent event) { viewtouchpoint[0] = event.getx(); viewtouchpoint[1] = event.gety(); rotatematrix.mappoints(childtouchpoint, viewtouchpoint); event.setlocation(childtouchpoint[0], childtouchpoint[1]); boolean result = super.dispatchtouchevent(event); event.setlocation(viewtouchpoint[0], viewtouchpoint[1]); return result; } }
mainactivity.java
public class mainactivity extends appcompatactivity { mongolviewgroup viewgroup; edittext edittext; int newwidth = 300; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); viewgroup = (mongolviewgroup) findviewbyid(r.id.viewgroup); edittext = (edittext) findviewbyid(r.id.edittext); } public void buttonclicked(view view) { newwidth += 200; viewgroup.layoutparams params = viewgroup.getlayoutparams(); params.width=newwidth; viewgroup.setlayoutparams(params); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingbottom="@dimen/activity_vertical_margin" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" tools:context="com.example.mongolviewgrouptest.mainactivity"> <com.example.mongolviewgrouptest.mongolviewgroup android:id="@+id/viewgroup" android:layout_width="100dp" android:layout_height="200dp" android:background="@color/coloraccent"> <edittext android:id="@+id/edittext" android:layout_width="match_parent" android:layout_height="match_parent" android:textcolor="@android:color/black" android:background="@android:color/white"/> </com.example.mongolviewgrouptest.mongolviewgroup> <button android:text="button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/button" android:onclick="buttonclicked" android:layout_alignparenttop="true" android:layout_alignparentright="true" android:layout_alignparentend="true"/> </relativelayout>
- you're not recalculating
viewrectrotated
edittext when viewgroup'sonlayout(...)
method called again. - since
anglechanged
set false (and never changes) after viewgroups first layout, part calculatesleft
,right
,top
,bottom
values edittext skipped time after first time when viewgroup requestslayout (when change height or width). - as such, edittext still laid out same
left
,right
,top
,bottom
values laid out with.
do away anglechanged
, should work fine. so:
@override protected void onlayout(boolean changed, int left, int top, int right, int bottom) { final rectf layoutrect = temprectf1; final rectf layoutrectrotated = temprectf2; layoutrect.set(0, 0, right - left, bottom - top); rotatematrix.setrotate(angle, layoutrect.centerx(), layoutrect.centery()); rotatematrix.postscale(-1, 1); rotatematrix.maprect(layoutrectrotated, layoutrect); layoutrectrotated.round(viewrectrotated); final view view = getview(); if (view != null) { view.layout(viewrectrotated.left, viewrectrotated.top, viewrectrotated.right, viewrectrotated.bottom); } }
i've tested , works fine way.
if need anglechanged
reason, make sure it's changed true
inside viewgroup's onmeasure
method viewrectrotated
recalculated again. wouldn't recommend that.
Comments
Post a Comment