gpt4 book ai didi

android.graphics 从一个 View 指向另一个 View 画一条线

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:10:19 25 4
gpt4 key购买 nike

我知道 android.graphics 很旧,但我在做一些简单的事情时遇到了麻烦。

I want to draw a line animation where one View points an arrow/line into another View

第一个按钮-------------------------------->第二个按钮

我已经尝试创建自定义 View 类并覆盖 onDraw(Canvas c) 方法,然后使用 drawLine(startX, startY, stopX, stopY , paint) 来自 Canvas 对象的方法。但是我不知道要获取哪个坐标才能将一个 View 指向另一个 View

我不想在 XML 布局中创建一个高度较小的静态 View,因为 View 可以由用户动态添加,我认为这是绘图动态线路是最好的方式。

请帮帮我。谢谢!

最佳答案

如果所有 View 都位于同一父布局上,则可以更好地在 View 之间绘制线条。对于问题的条件(Second Button 恰好位于 First Button 的右侧),您可以使用这样的自定义布局:

public class ArrowLayout extends RelativeLayout {

public static final String PROPERTY_X = "PROPERTY_X";
public static final String PROPERTY_Y = "PROPERTY_Y";

private final static double ARROW_ANGLE = Math.PI / 6;
private final static double ARROW_SIZE = 50;

private Paint mPaint;

private boolean mDrawArrow = false;
private Point mPointFrom = new Point(); // current (during animation) arrow start point
private Point mPointTo = new Point(); // current (during animation) arrow end point

public ArrowLayout(Context context) {
super(context);
init();
}

public ArrowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

public ArrowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

public ArrowLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}

private void init() {
setWillNotDraw(false);
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLUE);
mPaint.setStrokeWidth(5);
}

@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
if (mDrawArrow) {
drawArrowLines(mPointFrom, mPointTo, canvas);
}
canvas.restore();
}

private Point calcPointFrom(Rect fromViewBounds, Rect toViewBounds) {
Point pointFrom = new Point();

pointFrom.x = fromViewBounds.right;
pointFrom.y = fromViewBounds.top + (fromViewBounds.bottom - fromViewBounds.top) / 2;

return pointFrom;
}


private Point calcPointTo(Rect fromViewBounds, Rect toViewBounds) {
Point pointTo = new Point();

pointTo.x = toViewBounds.left;
pointTo.y = toViewBounds.top + (toViewBounds.bottom - toViewBounds.top) / 2;

return pointTo;
}


private void drawArrowLines(Point pointFrom, Point pointTo, Canvas canvas) {
canvas.drawLine(pointFrom.x, pointFrom.y, pointTo.x, pointTo.y, mPaint);

double angle = Math.atan2(pointTo.y - pointFrom.y, pointTo.x - pointFrom.x);

int arrowX, arrowY;

arrowX = (int) (pointTo.x - ARROW_SIZE * Math.cos(angle + ARROW_ANGLE));
arrowY = (int) (pointTo.y - ARROW_SIZE * Math.sin(angle + ARROW_ANGLE));
canvas.drawLine(pointTo.x, pointTo.y, arrowX, arrowY, mPaint);

arrowX = (int) (pointTo.x - ARROW_SIZE * Math.cos(angle - ARROW_ANGLE));
arrowY = (int) (pointTo.y - ARROW_SIZE * Math.sin(angle - ARROW_ANGLE));
canvas.drawLine(pointTo.x, pointTo.y, arrowX, arrowY, mPaint);
}

public void animateArrows(int duration) {
mDrawArrow = true;

View fromView = getChildAt(0);
View toView = getChildAt(1);

// find from and to views bounds
Rect fromViewBounds = new Rect();
fromView.getDrawingRect(fromViewBounds);
offsetDescendantRectToMyCoords(fromView, fromViewBounds);

Rect toViewBounds = new Rect();
toView.getDrawingRect(toViewBounds);
offsetDescendantRectToMyCoords(toView, toViewBounds);

// calculate arrow sbegin and end points
Point pointFrom = calcPointFrom(fromViewBounds, toViewBounds);
Point pointTo = calcPointTo(fromViewBounds, toViewBounds);

ValueAnimator arrowAnimator = createArrowAnimator(pointFrom, pointTo, duration);
arrowAnimator.start();
}

private ValueAnimator createArrowAnimator(Point pointFrom, Point pointTo, int duration) {

final double angle = Math.atan2(pointTo.y - pointFrom.y, pointTo.x - pointFrom.x);

mPointFrom.x = pointFrom.x;
mPointFrom.y = pointFrom.y;

int firstX = (int) (pointFrom.x + ARROW_SIZE * Math.cos(angle));
int firstY = (int) (pointFrom.y + ARROW_SIZE * Math.sin(angle));

PropertyValuesHolder propertyX = PropertyValuesHolder.ofInt(PROPERTY_X, firstX, pointTo.x);
PropertyValuesHolder propertyY = PropertyValuesHolder.ofInt(PROPERTY_Y, firstY, pointTo.y);

ValueAnimator animator = new ValueAnimator();
animator.setValues(propertyX, propertyY);
animator.setDuration(duration);
// set other interpolator (if needed) here:
animator.setInterpolator(new AccelerateDecelerateInterpolator());

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mPointTo.x = (int) valueAnimator.getAnimatedValue(PROPERTY_X);
mPointTo.y = (int) valueAnimator.getAnimatedValue(PROPERTY_Y);

invalidate();
}
});

return animator;
}
}

.xml 布局如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_main"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<{YOUR_PACKAGE_NAME}.ArrowLayout
android:id="@+id/arrow_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">

<Button
android:id="@+id/first_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="First Button"/>

<Button
android:id="@+id/second_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Second Button"/>

</{YOUR_PACKAGE_NAME}.ArrowLayout>

</RelativeLayout>

MainActivity.java像:

public class MainActivity extends AppCompatActivity {

private ArrowLayout mArrowLayout;
private Button mFirstButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mArrowLayout = (ArrowLayout) findViewById(R.id.arrow_layout);

mFirstButton = (Button) findViewById(R.id.first_button);
mFirstButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mArrowLayout.animateArrows(1000);
}
});
}
}

你有类似的东西(在 First Button 点击):

[Arrow to View animated

对于其他情况(Second Button 恰好在 First Button 的左侧(或上方或下方)或更复杂的右上方/左下方等) ) 您应该修改计算箭头起点和终点的部分:

private Point calcPointFrom(Rect fromViewBounds, Rect toViewBounds) {
Point pointFrom = new Point();

// Second Button above
// ----------+----------
// | |
// Second Button tho the left + First Button + Second Button tho the right
// | |
// ----------+----------
// Second Button below
//
// + - is arrow start point position

if (toViewBounds to the right of fromViewBounds){
pointFrom.x = fromViewBounds.right;
pointFrom.y = fromViewBounds.top + (fromViewBounds.bottom - fromViewBounds.top) / 2;
} else if (toViewBounds to the left of fromViewBounds) {
pointFrom.x = fromViewBounds.left;
pointFrom.y = fromViewBounds.top + (fromViewBounds.bottom - fromViewBounds.top) / 2;
} else if () {
...
}

return pointFrom;
}

关于android.graphics 从一个 View 指向另一个 View 画一条线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51624500/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com