ImageView-高さが幅と一致していますか?


166

私はimageviewを持っています。幅をfill_parentにしたい。私はその高さが幅が最終的に何であれ何であれ欲しいです。例えば:

<ImageView
  android:layout_width="fill_parent"
  android:layout_height="whatever the width ends up being" />

独自のビュークラスを作成しなくても、レイアウトファイルでそのようなことが可能ですか?

ありがとう


これを行う方法を理解しましたか?アスペクト比を変えないでほしいと思います。これらの回答のほとんどは、画像を正方形にすることを前提としています。
アダム

@ジョーブローこれは非常に悪い方法です
アグレッサー

回答:


170

更新:2017年9月14日

以下のコメントによると、パーセントサポートライブラリはAndroidサポートライブラリ26.0.0で廃止されています。これは、新しい方法です。

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:1" />

</android.support.constraint.ConstraintLayout>

こちらをご覧ください

非推奨:

Android Developersによるこの投稿によると、PercentRelativeLayoutまたはPercentFrameLayout内で必要なものをラップし、その比率を指定するだけです。

<android.support.percent.PercentRelativeLayout 
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        app:layout_widthPercent="100%"
        app:layout_aspectRatio="100%"/>

</android.support.percent.PercentRelativeLayout>

8
この回答へのリンクは、Googleが提供する最もエレガントなソリューションです。私の場合、元の画像のアスペクト比に関係なく、画像を16:9の比率で表示したかったのです。よく働く。ありがとう!
2016

私の場合、このような解決策は機能しませんでした、これは機能しました!
Gooey

5
依存関係に「com.android.support:percent:23.3.0」を追加することを忘れないでください
Milad Faridnia

これは、このアプローチがその子コンテンツに基づいて高さを計算するWrappedViewPagerに問題があるように見えます。似WrappedViewPagerのソースgist.github.com/egslava/589b82a6add9c816a007
SHA

1
Percent Supportモジュールは、Androidサポートライブラリ26.0.0から非推奨になりました。出典:developer.android.com/topic/libraries/support-library/...
MHogge

97

多分これはあなたの質問に答えます:

<ImageView
    android:id="@+id/cover_image"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true" />

scaleTypeこの特定の状況では、属性を無視できます。


12
うん、それは無用だ
Fattie

4
それは必然的に役に立たないわけではありません。これは私の使用法では問題なく動作します。タイトルバーにアイコンがあり、正方形のままで高さを満たすようにスケーリングします。
Anubian Noob、2015

3
私の問題も解決しました。
Dielsonセールス、2015

最も簡単な方法!これはベストアンサーとしてマークする必要があります。
H.ファリッド

30

実行時にビューの幅がわかったら、LayoutParamsを使用してビューの高さを動的に設定できます。実行時にビューの幅を取得するには、Runnableスレッドを使用する必要があります。そうしないと、レイアウトがまだ描画されていないため、ビューの幅がわかる前に高さを設定しようとします。

問題の解決方法の例:

final FrameLayout mFrame = (FrameLayout) findViewById(R.id.frame_id);

    mFrame.post(new Runnable() {

        @Override
        public void run() {
            RelativeLayout.LayoutParams mParams;
            mParams = (RelativeLayout.LayoutParams) mFrame.getLayoutParams();
            mParams.height = mFrame.getWidth();
            mFrame.setLayoutParams(mParams);
            mFrame.postInvalidate();
        }
    });

LayoutParamsは、ビューが含まれている親ビューのタイプである必要があります。私のFrameLayoutは、xmlファイルのRelativeLayout内にあります。

    mFrame.postInvalidate();

UIスレッドとは別のスレッドでビューを強制的に再描画するために呼び出されます


4
特にRunnableでの素晴らしい回答、ありがとう!
jesses.co.tt 2014

1
これは機能しますが、理想的ではありません。ポストで実行すると、レイアウトが変更される前にビューが1回レンダリングされます。正しく描画する前に、間違った高さでコンテンツがフラッシュする可能性があります。以前に解決した方がよい。Regisの回答にonMeasure示されているように、解決が可能な最も早い瞬間は、カスタム中です。別の方法ですが、内部など、アダプターを介してレンダリングされるビューのみがMattの答えです。GridView
ToolmakerSteve 2017年

1
requestLayout()パラメータを設定した後に呼び出した後でのみうまくいきました。なぜでしょうか?
Divins Mathew 2017

mFrame.postInvalidate(); それが何をしたかであり、それがなければ私は見解を外していた。
Jacolack

17

私は、David Chuの回答をRecyclerViewアイテムに対して機能させることができず、ImageViewを親に制限する必要があることがわかりました。ImageViewの幅をに設定し、0dpその開始と終了を親に制限します。幅をに設定しwrap_contentたりmatch_parent、場合によっては機能したりするかどうかはわかりませんが、これは、ConstraintLayoutの子に親を設定させるためのより良い方法だと思います。

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintDimensionRatio="1:1"/>

</android.support.constraint.ConstraintLayout>

13

ここで私は常に幅が高さに等しいImageButtonを持つために何をしましたか(そして、一方向の愚かな空のマージンを避けます...これはSDKのバグと考えています...):

ImageButtonから拡張するSquareImageButtonクラスを定義しました。

package com.myproject;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageButton;

    public class SquareImageButton extends ImageButton {

        public SquareImageButton(Context context) {
        super(context);


        // TODO Auto-generated constructor stub
    }

    public SquareImageButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub

    }

    public SquareImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub

    }

    int squareDim = 1000000000;

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);


        int h = this.getMeasuredHeight();
        int w = this.getMeasuredWidth();
        int curSquareDim = Math.min(w, h);
        // Inside a viewholder or other grid element,
        // with dynamically added content that is not in the XML,
        // height may be 0.
        // In that case, use the other dimension.
        if (curSquareDim == 0)
            curSquareDim = Math.max(w, h);

        if(curSquareDim < squareDim)
        {
            squareDim = curSquareDim;
        }

        Log.d("MyApp", "h "+h+"w "+w+"squareDim "+squareDim);


        setMeasuredDimension(squareDim, squareDim);

    }

}

これが私のxmlです:

<com.myproject.SquareImageButton
            android:id="@+id/speakButton"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:scaleType="centerInside"
            android:src="@drawable/icon_rounded_no_shadow_144px"
            android:background="#00ff00"
            android:layout_alignTop="@+id/searchEditText"
            android:layout_alignBottom="@+id/searchEditText"
            android:layout_alignParentLeft="true"
           />

魅力的な作品!


うん、それが最良の答えです。(そして、OPの質問に本当に一致する唯一のもの)
Twometer

6

Android 26.0.0では、PercentRelativeLayoutは非推奨になりました

それを解決する最良の方法は、次のようにすることですConstraintLayout

<android.support.constraint.ConstraintLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

    <ImageView android:layout_width="match_parent"
               android:layout_height="0dp"
               android:scaleType="centerCrop"
               android:src="@drawable/you_image"                       
               app:layout_constraintDimensionRatio="1:1"/>


</android.support.constraint.ConstraintLayout>


これは、プロジェクトに追加する方法に関するチュートリアルConstraintLayoutです。


6

画像ビューが制約レイアウト内にある場合、次の制約を使用して正方形の画像ビューを作成できます

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:id="@+id/ivImageView"
    app:layout_constraintDimensionRatio="W,1:1"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"/>

5

レイアウトだけではできません。それを処理するための非常に単純なクラスを作成してしまいました。githubで確認できます。SquareImage.java大きなプロジェクトの一部ですが、コピーアンドペーストで修正できないものはありません(Apache 2.0でライセンスされています)

基本的に、高さ/幅を他の寸法に等しく設定する必要があります(スケーリングする方法によって異なります)。

注:scaleType属性を使用してカスタムクラスなしで正方形にすることもできますが、ビューの境界が表示されている画像を超えているため、近くに他のビューを配置すると問題になります。


3

ImageViewを画面の半分に設定するには、ImageViewのXMLに以下を追加する必要があります。

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    android:scaleType="fitXY"
    android:adjustViewBounds="true"/>

次に、高さをこの幅に等しく設定するには、コードでそれを行う必要があります。アダプターのgetViewメソッドでGridViewImageView高さを測定された幅に等しく設定します。

mImageView.getLayoutParams().height = mImageView.getMeasuredWidth();

3

今を通り過ぎる人のために、2017年に、あなたが望むものを達成するための新しい最善の方法は、次のようにConstraintLayoutを使用することです:

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:scaleType="centerCrop"
    app:layout_constraintDimensionRatio="1:1" />

また、レイアウトの必要に応じて、4つの方向すべてに制約を追加することを忘れないでください。

ConstraintLayoutでレスポンシブUIを構築する

さらに、現在では、PercentRelativeLayoutは非推奨になっています(Androidのドキュメントを参照)。


1

これが私がその問題をどのように解決したかです:

int pHeight =  picture.getHeight();
int pWidth = picture.getWidth();
int vWidth = preview.getWidth();
preview.getLayoutParams().height = (int)(vWidth*((double)pHeight/pWidth));

プレビュー-幅が「match_parent」に設定され、scaleTypeが「cropCenter」に設定されたimageView

picture-imageView srcで設定するビットマップオブジェクト。

それは私にはかなりうまくいきます。


このコードを配置する必要がある場所を説明していません。また= vw*ph/pw、単純なものではなく、なぜ行うのかについても説明していません= vw。(正方形のプレビューを強制するのではなく、ソース画像のアスペクト比を維持するためにこれを行うと思います。)
ToolmakerSteve

0

XMLレイアウトファイルでそれを行う方法はないと思いandroid:scaleTypeます。また、属性が期待どおりに機能しないと思います。
唯一の方法は、プログラムでそれを行うことです。幅をfill_parentに設定し、画面の幅をの高さとするViewか、View.getWidth()メソッドを使用できます。


0

ImageViewの「scaleType」関数は、ここで役立ちます。

このコードは、アスペクト比を維持し、画像を上部に配置します。

android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitStart"

これは、scaleTypeを使用することの可能性と外観を示す素晴らしい投稿です。

ImageView scaleTypeサンプル


「scaleType」はここでは役に立ちません。目標は、ImageView自体が常に正方形であり、その内部のイメージだけではないことです。scaleTypeを使用すると、ImageViewが画像より大きくなる場合があります。
ToolmakerSteve 2017年

0

私はこのようにしました-

layout.setMinimumHeight(layout.getWidth());
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.