2016-11-08 57 views
2

背景调整大小旋转定制的ViewGroup子类

我有一个自定义ViewGroup子类,旋转,反映其子视图子视图。目的是为了正确display traditional Mongolian text

我可以把这个任何东西ViewGroup,但对于我目前的项目,我把它放在EditText。 (I was never successful在短短的旋转,并直接镜像EditText。然而,这种自定义视图组中包裹它的工作。)

问题

我的问题是,当我尝试调整ViewGroup编程,其子视图没有得到适当的调整。我希望EditText与父代ViewGroup的大小相匹配,以便它看起来是单一视图。

MCVE

我做了一个新的项目,以显示该问题。该按钮增加ViewGroup的宽度(以红色显示)。图像显示项目开始(一切工作正常)和两个宽度增量。该EditText是白色的,但宽度和高度都设置为match_parent

enter image description here

整个项目代码如下是没有得到,甚至调整。

MongolViewGroup.java(自定义的ViewGroup旋转并反映其内容)

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> 

回答

3
  • 当您再次调用 ViewGroup的onLayout(...)方法时,您不会为您的EditText重新计算viewRectRotated
  • 由于angleChanged是您的ViewGroups先布局,再计算你的EditText 的leftrighttopbottom值后的第一次跳过任何时间之后的部分设置为false(永不改变)当你的ViewGroup requestsLayout(当你改变它的高度或宽度时)。
  • 因此,您的EditText仍然使用与最初布局的left,right,top, 和bottom值相同的布局。

废除angleChanged,它应该工作得很好。像这样:

@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); 
    } 
} 

我测试过这个,它的工作原理很好。

如果需要angleChanged以任何理由,那么就确保它改回true你的ViewGroup的onMeasure方法,以便viewRectRotated再次重新计算内。但我不会推荐这一点。

+0

这绝对清楚地解决了这个问题。非常感谢你!我不能早日奖励赏金,但我会迟一点。 – Suragch

+0

不客气。很高兴知道我可以提供帮助。 :d –