代码之家  ›  专栏  ›  技术社区  ›  android developer

如何使imageview与textview垂直居中,同时确保textview有足够的空间显示?

  •  0
  • android developer  · 技术社区  · 6 年前

    背景

    这是一个非常简单的问题。

    我想有一个imageview和textview居中,这样textview(和可选的更多视图)就在imageview下面,但应该始终显示(imageview可以缩小,如果需要,只要保持纵横比)。

    问题

    不知为什么,我想的所有方法都不起作用。总有一种情况(通常通过改变方向以减少可用空间而容易再现)没有显示textview。

    我试过的

    1. 最初,我所做的就是:

    ic_android_red.xml公司 -样本图像而不是原始图像。

    <vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="400dp"
            android:tint="#FF0009" android:viewportHeight="24.0"
            android:viewportWidth="24.0" android:width="400dp">
        <path android:fillColor="#FF000000"
              android:pathData="M6,18c0,0.55 0.45,1 1,1h1v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L11,19h2v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L16,19h1c0.55,0 1,-0.45 1,-1L18,8L6,8v10zM3.5,8C2.67,8 2,8.67 2,9.5v7c0,0.83 0.67,1.5 1.5,1.5S5,17.33 5,16.5v-7C5,8.67 4.33,8 3.5,8zM20.5,8c-0.83,0 -1.5,0.67 -1.5,1.5v7c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5v-7c0,-0.83 -0.67,-1.5 -1.5,-1.5zM15.53,2.16l1.3,-1.3c0.2,-0.2 0.2,-0.51 0,-0.71 -0.2,-0.2 -0.51,-0.2 -0.71,0l-1.48,1.48C13.85,1.23 12.95,1 12,1c-0.96,0 -1.86,0.23 -2.66,0.63L7.85,0.15c-0.2,-0.2 -0.51,-0.2 -0.71,0 -0.2,0.2 -0.2,0.51 0,0.71l1.31,1.31C6.97,3.26 6,5.01 6,7h12c0,-1.99 -0.97,-3.75 -2.47,-4.84zM10,5L9,5L9,4h1v1zM15,5h-1L14,4h1v1z"/>
    </vector>
    

    活动\主.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:tools="http://schemas.android.com/tools"
                  xmlns:app="http://schemas.android.com/apk/res-auto"
                  android:orientation="vertical"
                  android:layout_width="match_parent" android:gravity="center"
                  android:layout_height="match_parent"
                  tools:context=".MainActivity">
    
        <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content"
                   app:srcCompat="@drawable/ic_android_red"/>
    
        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Hello World!"/>
    
    </LinearLayout>
    

    在肖像画上,效果很好:

    enter image description here

    但在横向上,它可以避免完全显示文本视图:

    enter image description here

    1. 我试着用 NestedScrollView 具有 android:fillViewport="true" ,但除了至少滚动到它之外,它没有任何帮助。

    2. 我尝试将linearlayout分成两半(使用0px的权重和高度),这样顶部的imageview将设置为底部(我使用framelayout来包含它),而底部的imageview将其内容与顶部对齐并水平居中。但是看起来也很奇怪,也许是因为他们已经不在一起了。

    3. 我试着用 ConstraintLayout ,以便使用 app:layout_constraintVertical_chainStyle="packed" ,并且底部部分(textView)将 app:layout_constraintHeight_min="wrap" . 也没用。

    问题

    有什么简单的方法可以克服它吗?在中间同时显示两个视图,但优先于文本视图?

    目前,唯一接近被认为有效的解决方案是两半解决方案。

    2 回复  |  直到 6 年前
        1
  •  1
  •   android developer    6 年前

    这可以通过 ConstraintLayout 使用垂直包装链和 ImageView 具有 match_constraints ( 0dp )因为它的宽度和 wrap_content 因为它的高度。图像视图还将具有以下设置,以便在图像高于其宽度时将高度保持在约束范围内。(见 "Dimension Constraints" )

    app:layout_constrainedHeight="true"
    

    垂直包装链将 图片框 TextView 一起并在布局中垂直居中。

    匹配约束 图片框 将允许图像扩展和收缩以匹配边界,同时允许 文本框 放在图像正下方的。 如果不希望图像在需要时更改大小,请设置 图片框 包装物含量 而不是 匹配约束 并设置 app:layout_constrainedWidth="true" .

    先前的一篇文章是基于图像的1:1宽高比。此解决方案不限制纵横比。以下是布局工作的一些图像:

    带图像宽度的纵向模式>高度 enter image description here

    带图像宽度的横向模式>高度 enter image description here

    带图像高度的纵向模式>宽度 enter image description here

    带图像高度的横向模式>宽度 enter image description here

    我还添加了一些页边距,以便更好地查看视图的真实范围,但可以删除页边距。中文本的大小 文本框 也被增加,使其更可见,但可以是任何大小。

    <androidx.constraintlayout.widget.ConstraintLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
    <!-- ImageView width could also be android:layout_height="wrap_content" 
    with app:layout_constrainedWidth="true"-->
    
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"
            app:layout_constrainedHeight="true"
            app:layout_constraintBottom_toTopOf="@+id/textView"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_chainStyle="packed"
            app:srcCompat="@drawable/vertical_image" />
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:text="Hello World!"
            android:textSize="36sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/imageView" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    布局的关键是 app:layout_constrainedHeight=”true" which limits the height of the 图像浏览。从 documentation for ConstraintLayout: :

    包装内容:强制约束(在1.1中添加)

    如果维度被设置为包装内容,在1.1之前的版本中,它们将被视为文本维度——这意味着,约束不会限制生成的维度。一般来说,这已经足够了(而且速度更快),但在某些情况下,您可能希望使用wrap_内容,同时继续实施约束以限制生成的维度。在这种情况下,可以添加相应的属性之一:

       app:layout_constrainedWidth=”true|false”
       app:layout_constrainedHeight=”true|false”
    
        2
  •  0
  •   TheWanderer    6 年前

    试试这个:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        android:layout_width="match_parent" android:gravity="center"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <ImageView android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            app:srcCompat="@drawable/ic_android_red"
            />
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            />
    
    </LinearLayout>
    

    这就是结果(“分辨率”为1920x1080dpi):

    portrait

    landscape

    我已经改变了图像视图的高度和重量。一个高度 0dp 重量为 1 告诉android imageview应该占据尽可能多的空间,同时仍然允许其他元素 wrap_content 正确地展示。我还将imageview的宽度更改为 match_parent ,尽管这不是必需的。

    如果你想要比textview更复杂的东西,只要把它和textview一起包装在你想要的任何布局中,保持不变 包装物含量 高度尺寸。