web-dev-qa-db-ja.com

ImageViewをデバイス幅にスケーリングする

私のAndroidアプリでは、次のサイズ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のようなものですが、画像の一部だけでなくすべてを見ることができるように画像の比例高さも設定します。

編集の原因私はあなたを私の「奇妙な」探求と混同していることを知っています。

画像でお見せしたいと思います。これは私が私のレイアウトで現時点で得ているものです。画像を必要なだけ大きく拡大して、灰色の領域全体を塗りつぶしたいと思います。どうすればそれを達成できますか?

ScaleTypeCENTER_CROPに設定すると、これが表示されます

しかし、これは私が望んでいることではありません。なぜなら、画像全体が中央から一部だけ見えていないからです。

そして、これは私がそれを望んでいるものです:

これが私が達成しようとしていることを理解するのに役立つことを願っています。誰もがそれを行う方法を知っていますか?

編集2:

画面サイズよりも高さが大きい画像を表示しようとしているのは奇妙で少し混乱しているように見えるかもしれませんが、例のレイアウトではScrollViewを使用しているので、これで問題ありません。表示されていない領域を見たい場合はスクロールできます。

これが私がやろうとしていることを理解するのに役立つことを願っています。

15
OemerA

ScaleTypeのすべてのImageViewfill_parentwrap_contentで実際に試しましたが、どれも機能しませんでした。また、Googleで見つけたものをすべて試しましたが、何もうまくいかなかったので、自分で何かを思いつきました。

ImageViewが拡大縮小したいように画像を拡大縮小していないことは明らかだったので、自分で拡大縮小する必要がありました。ビットマップをスケーリングした後、新しいビットマップをImageViewの画像ソースとして設定します。これはかなりうまく機能し、G1とMotorola Milestone2で非常によく見えます。

そして、これが私のコードのすべての部分です

レイアウト:

<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() );
    }
}

Utilクラス

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);
    }

}

同じスケーリングを達成するためのより良いまたはより正確な方法がある場合 私にお知らせください そんな些細なことを成し遂げるのがとても難しいとは信じられないからです。

私はこれを行うためのより良い方法を本当に見たいと思っています。

読んでくれてありがとう。

29
OemerA

最も簡単な方法は、Android:adjustViewBounds = "true"をImageViewに追加し、スケールタイプを「fitCenter」に設定することです。

19
Marian

正確に、あなたが探しているものについて少し混乱しています。画面に合わせてスケーリングする場合は、3つのオプションがあり、比率を維持している場合はそのうちの2つが実行可能です。 ScaleType fitCenterを使用すると、画像が境界内に比例して収まります。または、centerCrop(試したと言っています)を使用して、画像の最短辺を伸ばしてコンテナに合わせることができます(つまり、一部が切り取られます)。より長い次元で)。トリミングしたり、不釣り合いにストレッチしたりせずに、幅と高さに合わせてストレッチすることはできません。

[〜#〜] edit [〜#〜]:さて、私は今あなたの主張を理解していると思います。まず、LinearLayoutを高さのwrap_contentに設定します。第二に、コードでは、これが私が考えることができるそれを行うことができる1つの方法です。最初に画面のサイズを取得し、次に新しいサイズで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);
        }
    }
}
3
kcoppock

私はどこでもグーグルで検索し、解決策を見つけることができませんでした。これが私がしたことであり、それは私のためにそしてスクロールビューでうまくいきました。

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>
3
vtlinh

ImageView.setScaleType()を介してプログラムで設定してみましたか?

setAdjustViewBounds( false )も役立つかもしれません。

編集:申し訳ありませんが、質問を読み間違えました。とにかく、setAdjustViewBounds()stillが役立つかもしれません。しかし、それを使用したことはありません。

2
Snailer

これらの画像をデバイスの全幅で表示したいと思います。

これは簡単です。マージン設定が間違っているだけです。これらの線を削除すると、画像がデバイスの全幅で表示されます。

Android:layout_marginLeft="18dip"
Android:layout_marginRight="18dip" 
2
user432209

私が望んでいたことをなんとか達成することができます。それはうまくいけばあなたの目的と同じです。

@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;
}
1
Hitesh Tailor

私はもう画像を見ていないし、質問は古いですが、誰かがこれを見つけて同じ問題を抱えている場合に備えて。 float screenWidth = getResources().getDisplayMetrics().widthPixelsを取得し、ImageViewLayoutParamtersをプログラムで設定して画像をscreenWidthにスケーリングする方がよいのではないでしょうか。ただのアイデア!!

1
Saad Farooq

これを行う方法の1つは、Android:adjustViewBounds = "true"をImageViewに設定し、xmlファイルでスケールタイプを "fitCenter"に設定することです。これは期待どおりに機能するはずです。 ImageView.adjustViewBounds(true)およびImageView.setScaleType(ScaleType.FIT_CENTER)を設定することにより、これをプログラムで行うこともできます。

0
Parag Agrawal