如何旋转TextView而不剪切其边界?

时间:2013-01-18 13:18:58

标签: android android-canvas

我正在尝试使用TextView

来轮换我的canvas.rotate()子类
canvas.save();

final int w = getWidth();
final int h = getHeight();

float px = w/2f;
float py = h/2f;
canvas.rotate(mAngle, px, py);

super.draw(canvas);

canvas.restore();

旋转TextView,但我的视图边界被剪裁:

illustration

我知道这是因为我的视图大小 - 它在旋转期间不会改变。但是如果我在onMeasure中更改宽度\高度问题仍将存在 - 我正在使用LayoutParams.WRAP_CONTENT,因此TextView只需根据setMeasuredDimensions中提供的值更改其大小。

我该如何解决这个问题?

4 个答案:

答案 0 :(得分:3)

我认为这里的整个问题是你正在使用WRAP_CONTENT。当您这样做时,视图的剪辑矩形是文本内容的大小。解决问题的最简单方法是使用填充。像这样的东西对我来说很好:

<com.example.twistedtext.TwistedTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="30dp"
    android:gravity="center"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    twistedtext:rotation="30.0f"
    android:text="@string/hello_world" />

当然,如果你这样做,你将不得不为每个内容选择略有不同的填充。如果你不能这样做,请覆盖onMeasure,这样就完成了TextView的onMeasure所做的事情,然后根据旋转的需要添加相应的填充。

稍后添加: 实际上,弄清楚这很有趣。我有以下onMeasure,它运作得很好:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int w = getMeasuredWidth();
    int h = getMeasuredHeight();
    w = (int) Math.round(w * cosA + h * sinA);
    h = (int) Math.round(h * cosA + w * sinA);
    setMeasuredDimension(w, h);
}

唯一剩下的问题是文本根据预旋转尺寸进行包装。你也必须解决这个问题......

当设置了mAngle时,会计算sinA和cosA。

答案 1 :(得分:2)

好的,如果您无法在当前视图层次结构中旋转textView,则应在另一个视图层次结构中对其进行动画处理。

创建textView的位图represantation。像ImageView一样使用此位图的持有者。将imageView连接到另一个位于顶部且不会被裁剪的布局。隐藏您的textView。在ImageView上运行动画。动画完成后,更新textView表示,显示textView并删除ImageView。

我无法找到您想要的确切代码示例,但请查看this one。互动的地方是:

mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
mWindowManager.addView(YOUR_VIEW_WITH_ANIMATION, mWindowParams);

答案 2 :(得分:2)

G. Blake Meike提供的第一个解决方案是一个很好的开始,但是有很多问题需要解决。

为了克服问题,还有另一种方法。这很简单,但通常不应该使用(因为我刚从原始的android源代码中删除了不必要的东西)。要控制具体View的绘制,您可以覆盖其父级的drawChild方法(是的,您需要自己的ViewGroup子类或更具体的类似FrameLayout的东西)。以下是我的解决方案示例:

@Override
protected boolean drawChild(Canvas canvas, View child, long time) {
    //TextBaloon - is view that I'm trying to rotate
    if(!(child instanceof TextBaloon)) {
        return super.drawChild(canvas, child, time);
    }

    final int width = child.getWidth();
    final int height = child.getHeight();

    final int left = child.getLeft();
    final int top = child.getTop();
    final int right = left + width;
    final int bottom = top + height;

    int restoreTo = canvas.save();

    canvas.translate(left, top);

    invalidate(left - width, top - height, right + width, bottom + height);
    child.draw(canvas);

    canvas.restoreToCount(restoreTo);

    return true;
}

主要思想是我向孩子授予非剪裁画布。

答案 3 :(得分:1)

你可以查看https://github.com/grantland/android-autofittextview 特别是它的refitText()方法。

旋转你的Textview毕竟应该导致onMeasure()方法的调用,所有的魔法开始。

相关问题