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
viewrectrotatededittext when viewgroup'sonlayout(...)method called again. - since
anglechangedset false (and never changes) after viewgroups first layout, part calculatesleft,right,top,bottomvalues edittext skipped time after first time when viewgroup requestslayout (when change height or width). - as such, edittext still laid out same
left,right,top,bottomvalues 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