ImageView - có chiều rộng khớp chiều cao?


166

Tôi có một cái nhìn tưởng tượng. Tôi muốn chiều rộng của nó là fill_parent. Tôi muốn chiều cao của nó là bất cứ chiều rộng nào. Ví dụ:

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

Là một cái gì đó như thế có thể trong một tập tin bố trí mà không cần phải tạo lớp xem của riêng tôi?

Cảm ơn


Bạn đã tìm ra cách để làm điều này? Tôi giả sử bạn muốn tỷ lệ khung hình được giữ nguyên. Hầu hết các câu trả lời cho rằng bạn muốn hình ảnh vuông.
Adam

@Joe Blow đó là một chặng đường rất xấu để làm điều đó
Aggressor

Câu trả lời:


170

Cập nhật: ngày 14 tháng 9 năm 2017

Theo nhận xét bên dưới, thư viện phần trăm hỗ trợ không được chấp nhận kể từ Thư viện hỗ trợ Android 26.0.0. Đây là cách mới để làm điều đó:

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

Xem tại đây

Không dùng nữa

Theo bài đăng này của Nhà phát triển Android, tất cả những gì bạn cần làm bây giờ là gói bất cứ thứ gì bạn muốn trong PercentRelativeLayout hoặc PercentFrameLayout, sau đó chỉ định tỷ lệ của nó, như vậy

<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
Liên kết câu trả lời này có giải pháp thanh lịch nhất được cung cấp cho Google. Trong trường hợp của tôi, tôi muốn hình ảnh được hiển thị theo tỷ lệ 16: 9 bất kể tỷ lệ khung hình gốc là bao nhiêu. Công trình tuyệt vời. Cảm ơn!
LET

Tôi là trường hợp của tôi, giải pháp như cái này không hiệu quả, cái này thì có!
Gooey

5
đừng quên thêm 'biên dịch com.android.support:percent:23.3.0' trong phần phụ thuộc của bạn
Milad Faridnia

Điều này có vẻ như cách tiếp cận này đang gặp vấn đề với WrappingViewPager tính toán chiều cao dựa trên nội dung con của nó. Nguồn cho WrappingViewPager tương tự như gist.github.com/egslava/589b82a6add9c816a007
sha

1
Mô-đun Hỗ trợ Phần trăm đã không được chấp nhận đã bị từ chối kể từ thư viện hỗ trợ Android 26.0.0. Nguồn: developer.android.com/topic/lologists/support-l
Library / từ

96

Có lẽ điều này sẽ trả lời câu hỏi của bạn:

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

Bạn có thể bỏ qua scaleTypethuộc tính cho tình huống cụ thể này.


12
Phải

4
Nó không vô dụng. Điều này hoạt động tốt cho việc sử dụng của tôi, tôi có một biểu tượng trên thanh tiêu đề tôi muốn chia tỷ lệ để lấp đầy chiều cao trong khi hình vuông còn lại.
Anubian Noob

3
Giải quyết vấn đề của tôi quá.
Doanh số Dielson

Cách dễ nhất! Điều này nên được đánh dấu là câu trả lời tốt nhất.
H. Farid

30

Điều này có thể được thực hiện bằng cách sử dụng LayoutParams để tự động đặt chiều cao Lượt xem khi bạn biết chiều rộng Lượt xem khi chạy. Bạn cần sử dụng một chuỗi Runnable để có được độ rộng Lượt xem khi chạy hoặc nếu không bạn sẽ cố gắng đặt Chiều cao trước khi bạn biết chiều rộng của Chế độ xem vì bố cục chưa được vẽ.

Ví dụ về cách tôi giải quyết vấn đề của mình:

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 phải thuộc loại Chế độ xem chính mà chế độ xem của bạn. Khung hình của tôi nằm trong RelativeLayout trong tệp xml.

    mFrame.postInvalidate();

được gọi để buộc chế độ xem vẽ lại trong khi trên một luồng riêng biệt hơn luồng UI


4
câu trả lời tuyệt vời, đặc biệt là với Runnable, cảm ơn!
jesses.co.tt

1
Trong khi điều này hoạt động, nó không lý tưởng. Chạy trên bài viết có nghĩa là khung nhìn hiển thị một lần trước khi bố cục thay đổi. Có thể cho phép flash nội dung ở độ cao sai, trước khi vẽ chính xác. Tốt hơn để giải quyết sớm hơn. Thời điểm sớm nhất có thể giải quyết là trong một tùy chỉnh onMeasure, như thể hiện trong câu trả lời của Regis . Một cách khác, nhưng chỉ cho các chế độ xem được hiển thị qua bộ điều hợp, ví dụ bên trong GridView, là câu trả lời của Matt .
ToolmakerSteve

1
Vâng, nó chỉ làm việc cho tôi sau khi gọi requestLayout()sau khi thiết lập các tham số. tại sao lại như vậy
Divins Mathew

mFrame.postInvalidate (); là những gì đã làm nó, mà không có nó tôi đã nhận được ra khỏi vị trí.
Jacolack

17

Tôi không thể nhận được câu trả lời của David Chu để làm việc cho một mục RecyclerView và nhận ra rằng tôi cần phải hạn chế ImageView cho phụ huynh. Đặt chiều rộng ImageView thành 0dpvà giới hạn bắt đầu và kết thúc của nó thành cha. Tôi không chắc chắn nếu đặt chiều rộng thành wrap_contenthoặc match_parenthoạt động trong một số trường hợp, nhưng tôi nghĩ rằng đây là cách tốt hơn để đưa con của ConstraintLayout lấp đầy cha mẹ của nó.

<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

Ở đây tôi đã làm gì để có một ImageButton luôn có chiều rộng bằng với chiều cao của nó (và tránh các lề trống ngu ngốc theo một hướng ... mà tôi coi đó là một lỗi của SDK ...):

Tôi đã định nghĩa một lớp SquareImageButton mở rộng từ ImageButton:

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

    }

}

Đây là xml của tôi:

<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"
           />

Hoạt động như một lá bùa!


Yup, đó là câu trả lời tốt nhất. (và là người duy nhất thực sự phù hợp với câu hỏi của OP)
Twometer

6

Trong Android 26.0.0 PercentRelativeLayout đã không được dùng nữa .

Cách tốt nhất để giải quyết nó bây giờ là ConstraintLayoutnhư thế này:

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


Đây là một hướng dẫn về cách thêm ConstraintLayoutvào dự án của bạn.


6

Nếu chế độ xem hình ảnh của bạn nằm trong bố cục ràng buộc, bạn có thể sử dụng các ràng buộc sau để tạo chế độ xem hình vuông

<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

Bạn không thể làm điều đó với bố cục một mình, tôi đã thử. Cuối cùng tôi đã viết một lớp rất đơn giản để xử lý nó, bạn có thể kiểm tra nó trên github. SquareImage.java là một phần của dự án lớn hơn nhưng không có gì sao chép và dán không thể sửa chữa (được cấp phép theo Apache 2.0)

Về cơ bản, bạn chỉ cần đặt chiều cao / chiều rộng bằng với kích thước khác (tùy thuộc vào cách bạn muốn chia tỷ lệ)

Lưu ý: Bạn có thể làm cho hình vuông không có lớp tùy chỉnh bằng cách sử dụng scaleTypethuộc tính nhưng giới hạn của chế độ xem vượt ra ngoài hình ảnh hiển thị, điều này khiến nó trở thành vấn đề nếu bạn đặt các chế độ xem khác gần nó.


3

Để đặt ImageView của bạn bằng một nửa màn hình, bạn cần thêm đoạn sau vào XML cho ImageView:

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

Để sau đó đặt chiều cao bằng chiều rộng này, bạn cần thực hiện bằng mã. Trong getViewphương thức GridViewbộ điều hợp của bạn , đặt ImageViewchiều cao bằng chiều rộng đo được của nó:

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

3

Đối với những người đi ngang qua bây giờ, vào năm 2017, cách tốt nhất mới để đạt được những gì bạn muốn là sử dụng ConstraintLayout như thế này:

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

Và đừng quên thêm các ràng buộc cho tất cả bốn hướng khi bố trí của bạn cần.

Xây dựng giao diện người dùng đáp ứng với ConstraintLayout

Hơn nữa, đến bây giờ, PercentRelativeLayout đã không được chấp nhận (xem tài liệu Android ).


1

Đây là cách tôi giải quyết vấn đề đó:

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

xem trước - imageView với chiều rộng được đặt thành "match_parent" và scaleType thành "cropCenter"

hình ảnh - Đối tượng Bitmap để thiết lập trong imageView src.

Điều đó làm việc khá tốt đối với tôi.


Bạn đã không giải thích nơi mã này phải được đặt. Bạn cũng chưa giải thích lý do tại sao bạn làm = vw*ph/pwthay vì đơn giản hơn = vw. (Tôi nghĩ rằng bạn làm điều này để duy trì tỷ lệ khung hình của hình ảnh nguồn, thay vì buộc xem trước hình vuông.)
ToolmakerSteve

0

Tôi không nghĩ có bất kỳ cách nào bạn có thể làm điều đó trong tệp bố cục XML và tôi không nghĩ android:scaleTypethuộc tính sẽ hoạt động như bạn muốn.
Cách duy nhất là làm điều đó theo chương trình. Bạn có thể đặt chiều rộng thành fill_parent và có thể lấy chiều rộng màn hình làm chiều cao của phương thức Viewhoặc có thể sử dụng View.getWidth().


0

Chức năng "scaleType" của ImageView có thể giúp bạn ở đây.

Mã này sẽ giữ tỷ lệ khung hình và định vị hình ảnh ở trên cùng:

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

Đây là một bài viết tuyệt vời cho thấy các khả năng và sự xuất hiện từ việc sử dụng scaleType.

Mẫu ImageView scaleType


"scaleType" không giúp được gì ở đây. Mục tiêu là để ImageView luôn luôn vuông, không chỉ là hình ảnh bên trong nó. Với scaleType, ImageView có thể lớn hơn hình ảnh.
ToolmakerSteve

0

tôi đã làm như thế này -

layout.setMinimumHeight(layout.getWidth());
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.