[java] Android : 가로 세로 비율을 유지하면서 이미지를 화면 너비로 늘리는 방법은 무엇입니까?

이미지 (크기는 알 수 없지만 항상 대략 정사각형)를 다운로드하여 화면을 가로로 채우고 모든 화면 크기에서 이미지의 가로 세로 비율을 유지하기 위해 세로로 늘어나도록 표시하고 싶습니다. 다음은 내 (작동하지 않는) 코드입니다. 이미지를 가로로 늘리지 만 세로로는 늘이지 않기 때문에 스쿼시됩니다.

ImageView mainImageView = new ImageView(context);
    mainImageView.setImageBitmap(mainImage); //downloaded from server
    mainImageView.setScaleType(ScaleType.FIT_XY);
    //mainImageView.setAdjustViewBounds(true); 
    //with this line enabled, just scales image down
    addView(mainImageView,new LinearLayout.LayoutParams(
            LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));



답변

사용자 지정보기로이를 수행했습니다. layout_width = “fill_parent”및 layout_height = “wrap_content”를 설정하고 적절한 드로어 블을 가리 킵니다.

public class Banner extends View {

  private final Drawable logo;

  public Banner(Context context) {
    super(context);
    logo = context.getResources().getDrawable(R.drawable.banner);
    setBackgroundDrawable(logo);
  }

  public Banner(Context context, AttributeSet attrs) {
    super(context, attrs);
    logo = context.getResources().getDrawable(R.drawable.banner);
    setBackgroundDrawable(logo);
  }

  public Banner(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    logo = context.getResources().getDrawable(R.drawable.banner);
    setBackgroundDrawable(logo);
  }

  @Override protected void onMeasure(int widthMeasureSpec,
      int heightMeasureSpec) {
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = width * logo.getIntrinsicHeight() / logo.getIntrinsicWidth();
    setMeasuredDimension(width, height);
  }
}


답변

결국, 저는 수동으로 치수를 생성했습니다.

DisplayMetrics dm = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = width * mainImage.getHeight() / mainImage.getWidth(); //mainImage is the Bitmap I'm drawing
addView(mainImageView,new LinearLayout.LayoutParams(
        width, height));


답변

방금 소스 코드를 읽었 ImageView으며이 스레드에서 서브 클래 싱 솔루션을 사용하지 않고는 기본적으로 불가능합니다. 에서 ImageView.onMeasure우리는이 라인에 도착 :

        // Get the max possible width given our constraints
        widthSize = resolveAdjustedSize(w + pleft + pright, mMaxWidth, widthMeasureSpec);

        // Get the max possible height given our constraints
        heightSize = resolveAdjustedSize(h + ptop + pbottom, mMaxHeight, heightMeasureSpec);

이미지의 크기는 어디 h이며 패딩입니다.wp*

그리고:

private int resolveAdjustedSize(int desiredSize, int maxSize,
                               int measureSpec) {
    ...
    switch (specMode) {
        case MeasureSpec.UNSPECIFIED:
            /* Parent says we can be as big as we want. Just don't be larger
               than max size imposed on ourselves.
            */
            result = Math.min(desiredSize, maxSize);

따라서 layout_height="wrap_content"를 설정 widthSize = w + pleft + pright하면 최대 너비가 이미지 너비와 같습니다.

, 정확한 크기를 설정하지 않으면 이미지가 확대되지 않습니다 . 나는 이것이 버그라고 생각하지만, 구글이이를 알리거나 고칠 수 있기를 바랍니다. 편집 : 내 말을 먹고 버그 보고서를 제출 했으며 향후 릴리스에서 수정되었다고합니다!

또 다른 해결책

여기에 또 다른 서브 클래스 해결 방법이지만, 당신이 해야한다 (이론, 정말 많이 테스트하지 않았습니다!) 어디서나 그것을 사용할 수 있습니다 ImageView. 그것을 사용하려면 layout_width="match_parent", 및 layout_height="wrap_content". 허용되는 솔루션보다 훨씬 더 일반적입니다. 예를 들어 너비에 맞추는 것뿐만 아니라 높이에 맞추기를 할 수 있습니다.

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;

// This works around the issue described here: http://stackoverflow.com/a/12675430/265521
public class StretchyImageView extends ImageView
{

    public StretchyImageView(Context context)
    {
        super(context);
    }

    public StretchyImageView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public StretchyImageView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // Call super() so that resolveUri() is called.
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // If there's no drawable we can just use the result from super.
        if (getDrawable() == null)
            return;

        final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

        int w = getDrawable().getIntrinsicWidth();
        int h = getDrawable().getIntrinsicHeight();
        if (w <= 0)
            w = 1;
        if (h <= 0)
            h = 1;

        // Desired aspect ratio of the view's contents (not including padding)
        float desiredAspect = (float) w / (float) h;

        // We are allowed to change the view's width
        boolean resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;

        // We are allowed to change the view's height
        boolean resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;

        int pleft = getPaddingLeft();
        int pright = getPaddingRight();
        int ptop = getPaddingTop();
        int pbottom = getPaddingBottom();

        // Get the sizes that ImageView decided on.
        int widthSize = getMeasuredWidth();
        int heightSize = getMeasuredHeight();

        if (resizeWidth && !resizeHeight)
        {
            // Resize the width to the height, maintaining aspect ratio.
            int newWidth = (int) (desiredAspect * (heightSize - ptop - pbottom)) + pleft + pright;
            setMeasuredDimension(newWidth, heightSize);
        }
        else if (resizeHeight && !resizeWidth)
        {
            int newHeight = (int) ((widthSize - pleft - pright) / desiredAspect) + ptop + pbottom;
            setMeasuredDimension(widthSize, newHeight);
        }
    }
}


답변

adjustViewBounds를 true로 설정하고 LinearLayout 뷰 그룹을 사용하는 것이 저에게 매우 효과적이었습니다. 장치 메트릭을 하위 클래스로 분류하거나 요청할 필요가 없습니다.

//NOTE: "this" is a subclass of LinearLayout
ImageView splashImageView = new ImageView(context);
splashImageView.setImageResource(R.drawable.splash);
splashImageView.setAdjustViewBounds(true);
addView(splashImageView);


답변

저는 AGES를 위해이 문제를 어떤 형태로든 고심하고 있습니다. 감사합니다. 감사합니다 …. 🙂

View를 확장하고 onMeasure를 재정의함으로써 Bob Lee가 한 일에서 일반화 가능한 솔루션을 얻을 수 있다는 점을 지적하고 싶었습니다. 그렇게하면 원하는 드로어 블과 함께 사용할 수 있으며 이미지가 없어도 깨지지 않습니다.

    public class CardImageView extends View {
        public CardImageView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

        public CardImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public CardImageView(Context context) {
            super(context);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            Drawable bg = getBackground();
            if (bg != null) {
                int width = MeasureSpec.getSize(widthMeasureSpec);
                int height = width * bg.getIntrinsicHeight() / bg.getIntrinsicWidth();
                setMeasuredDimension(width,height);
            }
            else {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            }
        }
    }


답변

어떤 경우에는이 마법의 공식이 문제를 아름답게 해결합니다.

다른 플랫폼에서이 문제를 해결하는 데 어려움을 겪고있는 사람을 위해 “크기 및 모양에 맞게” 옵션이 Android에서 아름답게 처리되지만 찾기가 어렵습니다.

일반적으로 다음 조합을 원합니다.

  • 너비 일치 부모,
  • 높이 포장 내용,
  • adjustViewBounds 켜짐 (원문)
  • 스케일 fitCenter
  • cropToPadding OFF (원문)

그렇다면 그것은 자동적이고 놀랍습니다.

당신이 iOS 개발자라면, 안드로이드에서 테이블 뷰에서 “완전히 동적 셀 높이”를 할 수 있다는 것은 정말 놀랍습니다. .. 오류, ListView를 의미합니다. 즐겨.

<com.parse.ParseImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/post_image"
    android:src="@drawable/icon_192"
    android:layout_margin="0dp"
    android:cropToPadding="false"
    android:adjustViewBounds="true"
    android:scaleType="fitCenter"
    android:background="#eff2eb"/>

여기에 이미지 설명 입력


답변

이 XML 코드 만 사용하여이를 달성했습니다. 일식이 높이를 렌더링하지 않아서 크기에 맞게 확장되는 경우 일 수 있습니다. 그러나 실제로 장치에서 실행하면 제대로 렌더링되고 원하는 결과를 제공합니다. (적어도 나에게는)

<FrameLayout
     android:layout_width="match_parent"
     android:layout_height="wrap_content">

     <ImageView
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:adjustViewBounds="true"
          android:scaleType="centerCrop"
          android:src="@drawable/whatever" />
</FrameLayout>