10

我正在尝试轮换我的TextViewusing子类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 被旋转,但是我的视图的边界被剪裁了:

插图

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

我怎么解决这个问题?

4

4 回答 4

4

我认为这里的整个问题是您正在使用 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。

于 2013-01-20T16:46:39.690 回答
2

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

创建您的 textView 的位图表示。使用此位图的支架,例如 ImageView。将 imageView 连接到另一个布局,该布局位于顶部且不会被裁剪。隐藏你的文本视图。在 ImageView 上运行动画。动画完成后,更新 textView 表示,显示 textView 并删除 ImageView。

我找不到您想要的确切代码示例,但请看一下这个。交集的地方是:

mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
mWindowManager.addView(YOUR_VIEW_WITH_ANIMATION, mWindowParams);
于 2013-01-20T15:03:14.283 回答
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;
}

主要想法是我将非剪辑画布授予孩子。

于 2013-01-21T13:31:07.573 回答
1

您可以查看https://github.com/grantland/android-autofittextview 尤其是它的 refitText() 方法。

毕竟,旋转您的 Textview 应该会调用 onMeasure() 方法,这是所有魔法的开始。

于 2013-01-20T15:25:01.693 回答