【问题标题】:Scaling ImageView to device width将 ImageView 缩放到设备宽度
【发布时间】:2011-06-20 03:30:47
【问题描述】:

在我的 Android 应用程序中,我有一个 Activity,它显示具有以下尺寸 244 x 330 的图像。 我想以全设备宽度显示这些图像。

我的布局文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <LinearLayout 
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:orientation="vertical">

            <ImageView android:id="@+id/news_image" 
                android:layout_height="fill_parent" 
                android:layout_width="fill_parent"
                android:layout_marginLeft="18dip"
                android:layout_marginRight="18dip"
                android:background="#aaaaaa" />


    </LinearLayout>

</ScrollView>

我尝试设置 ImageView 的 ScaleType,但没有按比例缩放 ImageView 的 ScalingType。 如何在横向模式和纵向模式下按比例缩放图像以适应整个屏幕?

基本上我想要的是 ScaleType.CENTER_CORP 之类的东西,但它也设置了图像的比例高度,因此我可以看到所有图像,而不仅仅是图像的一部分。

编辑因为我知道我的“奇怪”任务让你感到困惑。

我想用一张图片给你看。 这就是我目前的布局。我想通过根据需要缩放图像来填充整个灰色区域。我怎样才能做到这一点?

当我将ScaleType 设置为CENTER_CROP 时,我明白了

但这不是我想要的,因为你没有看到整个图像只是中心的一部分。

这就是我想要的:

我希望这可以帮助您了解我想要完成的工作。 有人知道怎么做吗?

编辑 2:

我试图显示高度大于屏幕尺寸的图像可能看起来很奇怪而且有点令人困惑,但由于我在示例布局中使用ScrollView,这应该没问题,用户如果他想查看未显示的区域,可以滚动。

希望这有助于理解我想要做什么。

【问题讨论】:

    标签: android layout imageview


    【解决方案1】:

    我用fill_parentwrap_content 尝试了ImageView 中的每个ScaleType,但没有一个起作用。我还尝试了我在 Google 上找到的所有内容,但也没有任何对我有用的东西,所以我自己想出了一些东西。

    很明显,ImageView 并没有像我想要的那样缩放我的图像,所以我必须自己缩放它。缩放位图后,我会将新位图设置为 ImageView 的图像源。这很好用,在 G1 和摩托罗拉 Milestone 2 上看起来也很好。

    这是我的所有代码

    布局:

    <ScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <LinearLayout 
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:id="@+id/news_wrapper">
    
                <ImageView android:id="@+id/news_image" 
                    android:layout_height="fill_parent"
                    android:layout_width="fill_parent"
                    android:layout_marginLeft="18dip"
                    android:layout_marginRight="18dip"
                    android:background="#aaaaaa" />
    
        </LinearLayout>
    
    </ScrollView>
    

    活动

    public class ScalingImages extends Activity {
    
        private ImageView imageView;
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.test_margin);
    
            this.imageView = (ImageView)findViewById(R.id.news_image);
    
            // The image is coming from resource folder but it could also 
            // load from the internet or whatever
            Drawable drawable = getResources().getDrawable(R.drawable.img);
            Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
    
            // Get scaling factor to fit the max possible width of the ImageView
            float scalingFactor = this.getBitmapScalingFactor(bitmap);
    
            // Create a new bitmap with the scaling factor
            Bitmap newBitmap = Util.ScaleBitmap(bitmap, scalingFactor);
    
            // Set the bitmap as the ImageView source
            this.imageView.setImageBitmap(newBitmap);
        }
    
        private float getBitmapScalingFactor(Bitmap bm) {
            // Get display width from device
            int displayWidth = getWindowManager().getDefaultDisplay().getWidth();
    
            // Get margin to use it for calculating to max width of the ImageView
            LinearLayout.LayoutParams layoutParams = 
                (LinearLayout.LayoutParams)this.imageView.getLayoutParams();
            int leftMargin = layoutParams.leftMargin;
            int rightMargin = layoutParams.rightMargin;
    
            // Calculate the max width of the imageView
            int imageViewWidth = displayWidth - (leftMargin + rightMargin);
    
            // Calculate scaling factor and return it
            return ( (float) imageViewWidth / (float) bm.getWidth() );
        }
    }
    

    实用类

    public class Util {
    
        public static Bitmap ScaleBitmap(Bitmap bm, float scalingFactor) {
            int scaleHeight = (int) (bm.getHeight() * scalingFactor);
            int scaleWidth = (int) (bm.getWidth() * scalingFactor);
    
            return Bitmap.createScaledBitmap(bm, scaleWidth, scaleHeight, true);
        }
    
    }
    

    如果有更好或更准确的方法来实现相同的缩放比例请告诉我,因为我不敢相信这样一件微不足道的事情竟然如此难以完成。

    我真的希望看到更好的方法来做到这一点。

    感谢您的阅读。

    【讨论】:

    • 感谢分享。应该有一个比例因子来做到这一点。
    • 非常感谢 - 我不敢相信没有更简单的方法可以做到这一点!
    • 我还浪费了大量时间尝试使用 xml 中的设置。感谢您发布自己的解决方案。
    • getWidth() 现在已弃用,所以我改用它...Point size = new Point(); getWindowManager().getDefaultDisplay().getSize(size); int displayWidth = size.x;
    【解决方案2】:

    最简单的方法是在ImageView中添加android:adjustViewBounds="true",并将缩放类型设置为“fitCenter”

    【讨论】:

    • 简单的需求和简单的解决方案——它对我来说很好用。 (这应该是正确答案!)
    • 这个解决方案很完美
    【解决方案3】:

    确切地说,对您要查找的内容有些困惑。如果要缩放以适应屏幕,则有三个选项,如果要保持比例,其中两个是可行的。您可以使用 ScaleType fitCenter,这将使图像按比例适合边界,或者您可以使用 centerCrop(您说过您尝试过),它将拉伸图像的最短边以适合容器(意味着有些会被裁剪掉在较长的维度上)。如果不进行裁剪或不成比例地拉伸,您就不能让它拉伸以适应宽度和高度。

    编辑:好的,我想我现在明白你的意思了。首先,我将您的 LinearLayout 设置为 wrap_content 的高度。其次,在代码中,这是我能想到的一种方法。您可能还有另一种方法可以做到这一点,首先获取屏幕尺寸,然后使用新尺寸执行createScaledBitmap,然后设置背景资源。

    final ImageView newsImage = (ImageView)findViewById(R.id.news_image);
    
    //get details on resolution from the display
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    
    //going to set what happens as the layout happens
    newsImage.getViewTreeObserver().addOnGlobalLayoutListener(
        new ViewTreeObserver.OnGlobalLayoutListener() {
    
            public void onGlobalLayout() {
                int oldHeight, oldWidth, newHeight, newWidth;
    
                //we want the new width to be as wide as the screen
                newWidth = metrics.widthPixels;
    
                oldHeight = newsImage.getDrawable().getIntrinsicHeight();
                oldWidth = newsImage.getDrawable().getIntrinsicWidth();
    
                //keeping the aspect ratio, the new height should be w1/h1 = w2/h2
                newHeight = Math.floor((oldHeight * newWidth) / oldWidth);
                LinearLayout.LayoutParams params = 
                    (LinearLayout.LayoutParams)newsImage.getLayoutParams();
                params.height = newHeight;
                params.width = newWidth;
                newsImage.setLayoutParams(params);
                newsImage.setScaleType(ScaleType.CENTER);
                newsImage.invalidate();
                newsImage.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        }
    }
    

    【讨论】:

    • 我试过了,但ScaleType.CENTER_CROP确实降低了高度。你能提供一个样品吗?我会再试一次(也许我在某个地方犯了错误)并发布我的结果。
    • 如果你想让它适合宽度,你必须削减高度。要做你想做的事,你会使用 fitXY 缩放类型,但它会不成比例地缩放。没有其他方法可以做到这一点。
    • 但我不想让图像适合屏幕的高度。如果图像大于显示高度,则用户可以滚动图像,因为我在示例中使用了 ScrollView。我想要的是适合宽度,但如果高度大于显示高度,则不要削减高度并使其可滚动。有什么建议吗?
    【解决方案4】:

    我到处搜索,找不到解决方案。 这是我所做的,它对我有用,并且带有滚动视图。

    XML 文件:

    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true" >
    
        <ImageView
            android:id="@+id/manga_page_image"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:adjustViewBounds="true"
            android:scaleType="fitCenter" />
    </ScrollView>
    

    【讨论】:

    • 确认!它也对我有用,它比通过代码缩放图像要容易得多
    【解决方案5】:

    您是否尝试过通过ImageView.setScaleType() 以编程方式设置它?

    setAdjustViewBounds( false ) 可能也会有所帮助。

    编辑:对不起,我误读了这个问题。无论如何,setAdjustViewBounds() 仍然 可能会有所帮助。不过没用过。

    【讨论】:

    • 我刚试过setAdjustViewBounds,但没有帮助。还有其他建议吗?也许我的编辑让我的目标更容易理解。
    【解决方案6】:

    我想完整展示这些图片 设备宽度。

    这很简单。你只是有错误的边距设置。删除这些行,您的图像将显示在整个设备宽度:

    android:layout_marginLeft="18dip"
    android:layout_marginRight="18dip" 
    

    【讨论】:

    • 这看起来很奇怪,但实际上我想要这些边距,否则它会像“粘”在屏幕上一样。除非那 18 个左右倾斜,否则我想使用整个屏幕尺寸。
    【解决方案7】:

    我再也看不到这些图片了,而且这个问题很老了,但以防万一其他人发现这个问题并遇到同样的问题。获取float screenWidth = getResources().getDisplayMetrics().widthPixels 并以编程方式设置ImageView LayoutParamters 以将图像缩放到screenWidth 不是更好吗?只是一个想法!

    【讨论】:

      【解决方案8】:

      设法实现我想要的,希望与您的目标相同:

      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.pgviewer);
      
          ImageView PgContainer = (ImageView)findViewById(R.id.imageView1);
      
          String Page = String.valueOf(getIntent().getExtras().getInt("Page"));
          try {
              PgContainer.setImageBitmap(getBitmapFromAsset(Page));
          } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
      
          PgContainer.setScaleType(ScaleType.FIT_CENTER);
          PgContainer.scrollTo(0, 0);
          PgContainer.setScrollBarStyle(0);
      }
      

      然后缩放位图:

      private Bitmap getBitmapFromAsset(String strName) throws IOException
      {
          AssetManager assetManager = getAssets();
          InputStream istr = assetManager.open(strName+".png");
          Bitmap bitmap = BitmapFactory.decodeStream(istr);
      
          float screenWidth = getResources().getDisplayMetrics().widthPixels;
          int ih=bitmap.getHeight();
          int iw=bitmap.getWidth();
          float scalefactor = screenWidth/iw;
          //w = 480, h=~
          //int newh = bitmap.getHeight()/bitmap.getWidth();
          return android.graphics.Bitmap.createScaledBitmap(bitmap, (int)(iw*scalefactor), (int)(ih*scalefactor), true);
          //return bitmap;
      }
      

      【讨论】:

        【解决方案9】:

        其中一种方法是通过将 android:adjustViewBounds="true" 设置为 ImageView 并在 xml 文件中将缩放类型设置为“fitCenter”。 这应该按预期工作。 您也可以通过设置 ImageView.adjustViewBounds(true) 和 ImageView.setScaleType(ScaleType.FIT_CENTER) 以编程方式执行此操作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-07-04
          • 2017-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多