当前位置: 首页 > 知识库问答 >
问题:

Android - 在更深层的现有视图上精确地绘制 ImageView

羊慈
2023-03-14

这是一个很难描述的情况,所以请耐心等待。我被要求制作一个有点像这样的“教练标记”屏幕:

但是,就我而言,我需要将一些底层图像“拉”到前面,并以不同的颜色显示它们以使它们脱颖而出。我无法确定这些图像在运行时之前的“帧”是什么。我的方法是添加一个覆盖整个屏幕的黑色半不透明视图(我称之为“窗帘”),然后将我需要的图像添加为具有不同颜色的窗帘子视图。编辑 这部分很容易,我不是在寻求帮助(这就是为什么建议这是建议问题的副本是不正确的)。

我不相信我可以使用 bringToFront()setTranslationZ(),因为这些方法不会将 ImageView 一直带到我的窗帘前面。因此,我要做的是获取图像视图相对于整个屏幕的确切“框架”(其 x、y、宽度和高度),然后尝试使用相同的可绘制对象和相同的帧添加新的图像视图。

同样重要的是要知道底层的‘视图’实际上是由多个视图组成的(包括一个滑动抽屉),这就是为什么我需要得到相对于屏幕的坐标。我希望这有意义。

我能够将新的 ImageView 绘制为具有正确颜色的窗帘的子视图,但图像的位置和大小相差甚远。如何才能在前一个图像视图的顶部绘制这个新的图像视图

我也对其他策略持开放态度(因为这个似乎不起作用)。谢谢你的帮助。

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

    ...

    ViewTreeObserver vto = mRootview.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            mRootview.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            mDrawerLayout.openDrawer(Gravity.LEFT);

            RelativeLayout curtain = addOpaqueCurtainToRootView();
            int frame[] = getFrameOfExistingImageView();
            addNewImageViewOnTopOfEverything(curtain, frame);
        }
    });
}

private RelativeLayout addOpaqueCurtainToRootView() {
    RelativeLayout curtain = new RelativeLayout(context);
    RelativeLayout.LayoutParams curtainParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
    curtain.setLayoutParams(curtainParams);
    curtain.setBackgroundColor(Color.argb(179, 0, 0, 0)); //70% opaque
    mRootview.addView(curtain);
    return curtain;
}

private int[] getFrameOfExistingImageView() {
    // proving that I have a reference to the original image
    mCurrentImage.setColorFilter(Color.rgb(255, 0, 0));

    int array[] = new int[2];
    mCurrentImage.getLocationOnScreen(array);
    Log.d(TAG, "width: " + Integer.toString(array[0]));
    Log.d(TAG, "height: " + Integer.toString(array[1]));
    Log.d(TAG, "x: " + Float.toString(mCurrentImage.getX()));
    Log.d(TAG, "y: " + Float.toString(mCurrentImage.getY()));

    int frame[] = new int[4]; // x,y,width,height
    frame[0] = (int)mCurrentImage.getX();
    frame[1] = (int)mCurrentImage.getY();
    frame[2] = array[0];
    frame[3] = array[1];
    return frame;
}

private void addNewImageViewOnTopOfEverything(RelativeLayout curtain, int[] frame) {
    ImageView iv = new ImageView(context);
    iv.setImageResource(R.drawable.imgView);
    iv.setColorFilter(Color.rgb(255, 255, 255));
    iv.setX(frame[0]);
    iv.setY(frame[1]);
    iv.setLayoutParams(new RelativeLayout.LayoutParams(frame[2], frame[3]));

    curtain.addView(iv);
}

共有1个答案

宇文飞羽
2023-03-14

我明白了。我有两个基本问题。

首先,我完全弄错了< code>ImageView的框架。我需要得到左侧和顶部的坐标,以及图像绘制后的高度和宽度。这是我如何做的(我实际上是转换到左,上,右,下,但其余的很容易):

private int[] getFrameOfImageView(ImageView imageView) {

    int array[] = new int[2];
    imageView.getLocationOnScreen(array);

    int frame[] = new int[4];

    frame[0] = array[0]; // left
    frame[1] = array[1]; // top
    frame[2] = array[0] + imageView.getWidth(); // right
    frame[3] = array[1] + imageView.getHeight(); // bottom

    return frame;
}

然后,我创建了一个新类来绘制。这是与我的OP最大的不同。最初,我想我可以将其添加为一个新的ImageView,并将其LayoutParams设置为我想要的位置。相反,我最终使用PaintCanvas来绘制、调整大小和放置:

public class CanvasPainter extends View {

    Context mContext;
    Drawable mDrawable;

    int mFrame[];
    int left;
    int top;
    int right;
    int bottom;
    int width;
    int height;

    private final int LEFT = 0;
    private final int TOP = 1;
    private final int RIGHT = 2;
    private final int BOTTOM = 3;

    public CanvasPainter(Context context, int frame[], Drawable drawable) {
        super(context);

        mContext = context;
        mFrame = frame;
        mDrawable = drawable;

        left = frame[LEFT];
        top = frame[TOP];
        right = frame[RIGHT];
        bottom = frame[BOTTOM];
        width = right - left;
        height = bottom - top;

    }

    public void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);


        Bitmap b = ((BitmapDrawable) mDrawable).getBitmap();
        Bitmap bitmapResized = Bitmap.createScaledBitmap(b, width, height, false);

        canvas.drawBitmap(bitmapResized, left, top, paint);
    }
}

所以,把这些放在一起,这一切都是从onCreate()组织起来的,就像这样;

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

    ... 

    mDrawerLayout.openDrawer(Gravity.LEFT);

    ViewTreeObserver vto = mRootview.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override 
        public void onGlobalLayout() { 

            mRootview.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            RelativeLayout curtain = addOpaqueCurtainToRootView();
            int frame[] = getFrameOfExistingImageView();
            Drawable d = ContextCompat.getDrawable(context, R.drawable.imgView);
            CanvasPainter canvasPainter = new CanvasPainter(context, mCurrentImg, frame, d);
            curtain.addView(canvasPainter);
        } 
    }); 
} 

这可能是一个有点模糊的问题,但我希望这能帮助一些人。

 类似资料:
  • 我该怎么做才能在我自己的视图上使用freehanf手指画?

  • 我正在开发一个应用程序,它有一个应用程序功能,可以在谷歌地图上显示团队作为标记。 我可以把自己显示为移动时更新的标记 问题是,标记仅在我第一次转到MapFragment时显示。当我导航到另一个片段并返回到地图时,我看到一个没有标记的空地图 尝试#3,请查看以前实现的历史记录,这些实现略有不同: 我的片段布局: 我的IncidentMapFragment代码,现在根据用户反馈进行更新。更新很少。请参

  • 注意:对于 Photoshop CC 之前的 Photoshop 版本,只有当您拥有 Photoshop Extended 时,本文所讨论的某些功能才可能可用。Photoshop 不提供单独的 Extended 版本。Photoshop Extended 中的所有功能是 Photoshop 的一部分。 在视频图层中绘制帧 可以在各个视频帧上进行编辑或绘制以创建动画、添加内容或移去不需要的细节。除了

  • 本文向大家介绍python在openstreetmap地图上绘制路线图的实现,包括了python在openstreetmap地图上绘制路线图的实现的使用技巧和注意事项,需要的朋友参考一下 利用python进行经纬度轨迹展示 嘿!各位好久不见,距离第一次发博客已经过去两年多了,本人也从本科生变成了研究生,好了书归正传,最近在做一个关于航班滑行路径轨迹的项目,目的是将航班的经纬度数据在地图上显现出来并

  • 我是Android新手,发现了很多东西。但现在我很沮丧。我想做一个六角形棋盘游戏,用瓷砖。我找到了很多芭蕾舞团,最后决定画出我想要的六边形。 我创建了一个从视图扩展的“Hex”类,添加了一些变量等等。以下是我在主XML布局中的内容: r=大小,x和y是画布上的偏移。以下是我在活动中看到的内容:主活动屏幕 但现在我想选择单十六进制。例如,我想选择左上角的,或右下角的。我在每个视图上都添加了OnCli

  • 我试图做一个简单的绘图(对于这个例子,做一个y=x^2的绘图就足够了),我想根据它们的大小设置点的颜色。 下面是我的简单示例,我说: 使用,它生成一个带有彩色点的绘图,但colorbar与彩色值不一致。(这是我的第一篇文章,无法发布图片)。使用命令给出正确的范围,但颜色仍处于关闭状态。 所以我有两个问题:(1)如何调整颜色以适应给定范围的色条?在我的真实数据中,在某些情况下,我看到的值在-50到5