如何通过自定义左侧和顶部坐标填充ImageView中的Image的Android

时间:2017-02-17 12:22:19

标签: android imageview android-recyclerview coordinates offset

我需要在Frame (多个图像帧)中显示一些图像,我有顶部坐标与每个图像的对应关系。

例如,我的图像坐标 100左起,100来自顶部,所以我需要做的只是显示 ImageView 中的图像从哪里开始的(100,100)

有人能告诉我怎么能没有Bitmap ,因为我需要在 RecyclerView 中显示带有多个图像的帧列表。

我使用TouchImageView.class进行缩放和移动功能来创建框架。

1。在我选择布局时,在屏幕截图下方,您可以清楚地看到两个图像彼此非常接近。我的意思是我选择每张图片的一半。

enter image description here

2。接下来是主屏幕,我需要重新绘制该图像,我有两个图像的左侧和顶部坐标。但我如何通过一些自定义x和y在ImageView中绘制图像。

enter image description here

用于在左侧和顶部填充ImageView内部图像的代码段 -

 img.setPadding((int) x, (int) y, 0, 0);

但仍然没有工作。

请给我一些建议,我已经完成了谷歌搜索,但没有为我的要求找到合适的解决方案。

建议真的很感激。

非常感谢提前。

亲切的问候。

5 个答案:

答案 0 :(得分:6)

更新:我在本文末尾添加了一个示例应用,以说明这一概念。

第二次更新:为示例应用添加了一些代码以适应xy扩展

我已经更改了示例应用,以包含适合图像的代码,无论是小于还是大于ImageView,视图大小与视图大小相符。这可能不是你想要的,但它应该让你进入球场。这是示例代码,因此确实可以在实际应用程序中容纳其他内容。例如,xScaleyScale在极端情况下可能会消极。我不确定如果他们这样做会发生什么,但可能是结果崩溃,所以边界检查是有序的。

如果我理解你要做什么,你想要一个固定大小的ImageView来显示你的不同部分 通过将图像的自定义(x,y)坐标设置为位于ImageView的(0,0)坐标,可以获得更大的图像。 这基本上是在顶部和左边缘上裁剪图像。

有很多不同的方法可以做到这一点,哪一个最适合你,将取决于你的确切需求, 但这是一种方式:

在代码中使用以下或某些变体:

float xOffset = -100;
float yOffset = -100;
ImageView imageView = (ImageView) findViewById(R.id.shiftedView);
Matrix matrix = new Matrix();

matrix.setTranslate(xOffset, yOffset);
imageView.setImageMatrix(matrix);

设置ImageView,如下所示。这里的关键是android:scaleType="matrix"

<ImageView
    android:id="@+id/shiftedView"
    android:layout_width="200dp"
    android:layout_height="match_parent"
    android:background="#FF00CCCC"
    android:scaleType="matrix"
    android:src="@drawable/image" />

我希望这会对你有所帮助。

示例应用

这是这个概念的快速模型。这个应用程序由主要活动和一个布局组成。您必须提供一个图像作为ImageView的来源,以了解其工作原理。

七个按钮会在ImageView的布局内点击一下,左右,上下移动图像。 “Fit X”和“Fit Y”按钮会将图像缩放到ImageView中可用的相应尺寸。 “重置”按钮会将图像重新设置为ImageView的原始默认设置。

<强> MainActivity.java

package com.example.imageshift;

import android.graphics.Matrix;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    ImageView imageView;
    float xOffset = 0f;
    float yOffset = 0f;
    float xScale = 1.0f;
    float yScale = 1.0f;

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

        imageView = (ImageView) findViewById(R.id.shiftedView);
        findViewById(R.id.shiftUp).setOnClickListener(this);
        findViewById(R.id.shiftDown).setOnClickListener(this);
        findViewById(R.id.shiftLeft).setOnClickListener(this);
        findViewById(R.id.shiftRight).setOnClickListener(this);
        findViewById(R.id.shiftReset).setOnClickListener(this);
        findViewById(R.id.fitX).setOnClickListener(this);
        findViewById(R.id.fitY).setOnClickListener(this);
    }

    public void doMatrixTransformations() {
        Matrix matrix = new Matrix();

        matrix.setTranslate(xOffset, yOffset);
        matrix.postScale(xScale, yScale);
        imageView.setImageMatrix(matrix);
    }

    @Override
    public void onClick(View view) {
        final int shiftAmount = 50;

        switch (view.getId()) {
            case R.id.shiftUp:
                yOffset -= shiftAmount;
                break;
            case R.id.shiftDown:
                yOffset += shiftAmount;
                break;

            case R.id.shiftLeft:
                xOffset -= shiftAmount;
                break;

            case R.id.shiftRight:
                xOffset += shiftAmount;
                break;

            case R.id.fitX:
                xScale = (float) imageView.getWidth() / (
                        (float) imageView.getDrawable().getIntrinsicWidth() + xOffset);
                yScale = xScale;
                break;

            case R.id.fitY:
                yScale = (float) imageView.getHeight() /
                        ((float) imageView.getDrawable().getIntrinsicHeight() + yOffset);
                xScale = yScale;
                break;

            case R.id.shiftReset:
                xOffset = 0;
                yOffset = 0;
                xScale = 1.0f;
                yScale = 1.0f;
                break;
        }
        doMatrixTransformations();
    }
}

<强> 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="wrap_content"
    android:orientation="vertical"
    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.imageshift.MainActivity">

    <ImageView
        android:id="@+id/shiftedView"
        android:layout_width="200dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="0dp"
        android:layout_marginTop="0dp"
        android:padding="2dp"
        android:scaleType="matrix"
        android:src="@drawable/image" />

    <Button
        android:id="@+id/shiftUp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/shiftedView"
        android:text="Up" />

    <Button
        android:id="@+id/shiftDown"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/shiftUp"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/shiftedView"
        android:text="Down" />

    <Button
        android:id="@+id/shiftLeft"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/shiftDown"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/shiftedView"
        android:text="Left" />

    <Button
        android:id="@+id/shiftRight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/shiftLeft"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/shiftedView"
        android:text="Right" />

    <Button
        android:id="@+id/fitX"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/shiftRight"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/shiftedView"
        android:text="Fit X" />

    <Button
        android:id="@+id/fitY"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/fitX"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/shiftedView"
        android:text="Fit Y" />

    <Button
        android:id="@+id/shiftReset"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/fitY"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/shiftedView"
        android:text="Reset" />

</RelativeLayout>

答案 1 :(得分:3)

听起来你想要拍摄两张图片并根据两张图片的某种组合创建一个新图像。

有很多不同的方法可以解决这个问题。最直接的方法是使用Bitmaps。我能看到的两种主要方法是直接实现这一目标。

  1. 在一些常见父级中定位您的图像视图,并创建该父级的位图以用作生成的图像。

  2. 通过根据您自己的计算方法绘制图像视图的图像来自己创建一个位图,该计算应该模仿您的布局结构。

  3. 由于您似乎已经按照您希望生成的图像的方式显示屏幕上的两个图像,因此第一个图像将是最直接的,并且不会要求您重做计算您的布局和图像视图已经在执行。

    我们要做的是利用每个视图将自己绘制到画布上的事实,并且在一天结束时只是将自身转换为图像本身。要获得父布局的位图,您只需创建一个相同大小的位图,然后告诉您的父布局将自己绘制到位图的画布上,如下所示:

    private Bitmap getCombinedBitmap(View parentView) {
        Bitmap result = Bitmap.createBitmap(parentView.getWidth(), parentView.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(result);
        parentView.draw(canvas);
    
        return result;
    }
    

    但是,如果您不希望父级布局绘制到屏幕上,则可以通过将图像绘制到类似的画布上来创建所需的位图。在这里,我已经实现了您问题的第一个布局:

    private Bitmap getCombinedBitmap(Bitmap a, Bitmap b) {
        int aWidth = a.getWidth() / 2;
        int bWidth = b.getWidth() / 2;
        int resultHeight = a.getHeight() < b.getHeight()?  a.getHeight() : b.getHeight();
        Bitmap result = new Bitmap(aWidth + bWidth, resultHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(result);
    
        Rect aRect = new Rect(0, 0, aWidth, resultHeight);
        Rect aResultRect = new Rect(0, 0, aWidth, resultHeight);
        canvas.drawBitmap(a, aRect, aResultRect);
    
        Rect bRect = new Rect(0, 0, bWidth, resultHeight);
        Rect bResultRect = new Rect(bWidth, 0, bWidth, resultHeight);
        canvas.drawBitmap(b, bRect, bResultRect);
    
        return result;
    }
    

    在这个例子中,我选择了更清晰的代码而不是更优化的代码。您可以通过不创建任意数量的Rect等来优化这一点,并且通常可以简化计算。但是您可以使用此方法在单个位图上重新创建任何布局,您只需要更改计算。

    我们正在做的是首先创建一个位图,其宽度为第一个图像的一半加上第二个图像的一半,以及两个图像中最小的图像的高度。然后,我们将第一个图像的一部分视为最左边的半宽度,并且高度与结果高度一样高,我们将其绘制到我们的结果上。然后我们对第二个图像做同样的事情,除了这次该部分是最右边的半宽度。

    希望这有帮助。

答案 2 :(得分:3)

我必须承认,我并不是100%确定我明白你想做什么。如果我理解正确,您需要将ImageView放在另一个元素中(我使用FrameLayout显示示例,但您也可以使用LinearLayoutRelativeLayout)。然后在外部元素上设置填充。

<!-- we put the ImageView inside a Frame so that we can change -->
<!--    the padding size to create borders -->
<FrameLayout
    android:layout_width="140dp"
    android:layout_height="140dp"
    android:id="@+id/image_frame"
    >
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/image_view"
        />
</FrameLayout>

然后在代码中:(使用frame代替img

FrameLayout frame = (FrameLayout)itemLayout.findViewById(R.id.image_frame);
frame.setPadding((int) x, (int) y, 0, 0);

如果我明白你想做什么,就可以做到。

答案 3 :(得分:3)

您可以通过合并BitMaps轻松完成。

我创建了一个测试项目,该项目使用Glide加载2个图像位图,然后使用画布将它们合并到一个BitMap中,然后将其设置在任何ImageView上。

您还可以将图像保存在SD卡上的文件中,以避免每次都进行繁重的计算。它看起来像这样(Gif - https://github.com/hiteshsahu/Android-Merge-Bitmaps-With-Glide/blob/master/Art/demo.gif): -

enter image description here

我使用了一个图像视图作为我的Frame布局的背景,我使用了搜索栏来改变电影海报Raees的相对位置。您可以使用这些搜索栏更改任一位图的起始X和Y坐标。

我是怎么做到的: -

这是我如何做到的代码片段。这是不言自明的

 Glide.with(context)
                .load(R.drawable.raees)
                .asBitmap()
                .into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {

                        // Add Bitmap in Array and load next bitmap
                        arts[0] = resource;

                        Glide.with(context)
                                .load(R.drawable.raees_edited)
                                .asBitmap()
                                .into(new SimpleTarget<Bitmap>() {
                                    @Override
                                    public void onResourceReady(Bitmap resource1, GlideAnimation<? super Bitmap> glideAnimation) {

                                        // Both Bitmap loaded do the Merging
                                        arts[1] = resource1;

                                        //Set seekbars Max
                                        satrtX1SeekBar.setMax(arts[0].getWidth());
                                        satrtX2SeekBar.setMax(arts[1].getWidth());
                                        satrtY1SeekBar.setMax(arts[0].getHeight());
                                        satrtY2SeekBar.setMax(arts[1].getHeight());

                                        Bitmap bmOverlay = Bitmap.createBitmap(arts[0].getWidth(), arts[0].getHeight(), Bitmap.Config.ARGB_8888);
                                        Canvas canvas = new Canvas(bmOverlay);

                                        if (shouldDrawLeftHalf) {
                                            // Rect(left, top, right, bottom)
                                            canvas.drawBitmap(arts[0],
                                                    new Rect(0, 0, arts[0].getWidth() / 2, arts[0].getHeight()),
                                                    new Rect(0, 0, arts[0].getWidth() / 2, arts[0].getHeight()), null);

                                        } else {
                                            canvas.drawBitmap(arts[0], startX1, startY1, null);
                                        }

                                        if (shouldDrawRightHalf) {
                                            // Rect(left, top, right, bottom)
                                            canvas.drawBitmap(arts[1],
                                                    new Rect(arts[1].getWidth() / 2, 0, arts[0].getWidth(), arts[1].getHeight()),
                                                    new Rect(arts[1].getWidth() / 2, 0, arts[1].getWidth(), arts[1].getHeight()), null);
                                        } else {
                                            canvas.drawBitmap(arts[1], startX2, startY2, null);
                                        }


                                        background.setImageBitmap(bmOverlay);

                                        // saveToDisk("Test", bmOverlay);
                                    }
                                });
                    }
                });

您可以从My GitHub下载整个项目

https://github.com/hiteshsahu/Android-Merge-Bitmaps-With-Glide

答案 4 :(得分:1)

最终我找到了问题的解决方案 -

感谢您提供的所有帮助。

所以,基本上我有查看高度查看宽度顶部坐标左侧坐标原始图像高度原始图像宽度

  1. 我需要计算关于查看图片宽高比因素
  2. 以下是 -

    的公式
     float newAspectFactor = 0;
    
    
     if (viewHeight > viewWidth) {
     //Aspect factor for Height
     newAspectFactor = viewHeight / bean.getPostMedia().get(i).getImg_height();
    
     } else {
     //Aspect factor for Width
     newAspectFactor = viewWidth / bean.getPostMedia().get(i).getImg_width();
     }
    
     float imgNewHeight = newAspectFactor * imageHeight;
     float imgNewWidth = newAspectFactor * imageWidth;
     Logger.logsError(TAG, " Image New Height : " + imgNewHeight);
     Logger.logsError(TAG, " Image New Width : " + imgNewWidth);
    
     if (imgNewHeight < viewHeight) {
     newAspectFactor = viewHeight / bean.getPostMedia().get(i).getImg_height();
     } else if (imgNewWidth < viewWidth) {
     newAspectFactor = viewWidth / bean.getPostMedia().get(i).getImg_width();
     }
    
    1. 上下左坐标。

                  float x = 42.0;
                  float y = 0.0;
      
    2. 魔术从这里开始。

                  Matrix m = img.getImageMatrix();
                  RectF drawableRect = new RectF(x,
                          y,
                          ((x * newAspectFactor) + viewWidth) / newAspectFactor,
                          imageHeight);
                  RectF viewRect = new RectF(0,
                          0,
                          viewWidth,
                          viewHeight);
                  m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.FILL);
                  img.setImageMatrix(m);
                  img.setScaleType(ImageView.ScaleType.MATRIX);
                  imageLoaderNew.displayImage("IMAGE URL", img, optionsPostImg);