Android中FrameLayout中心视图无法正常工作

95

我有一个FrameLayout,其中包含两个控件: - 一个自定义视图,在其上绘制一张图片和一些文本 - 一个带有文字的TextView

我想将它们都居中在FrameLayout中,但我无法做到。TextView已经居中了,但我的自定义视图仍然停留在左侧,即使我将其可见。

<FrameLayout android:id="@+id/CompassMap"
               android:layout_width="fill_parent" 
               android:layout_height="wrap_content"
               android:layout_weight="1"
               android:gravity="center">

             <view class="com.MyView"
        android:id="@+id/myView"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal"
        android:visibility="gone"/>

                <TextView android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal"
        android:text="CENTERED" /> 
</FrameLayout>

对于Mathias,我的构造函数里并没有做任何操作,非常简单。

   public class MyMapView extends View {

private int xPos = 0; 
private int yPos = 0;
private Bitmap trackMap;

private Matrix backgroundMatrix;
private Paint backgroundPaint;

private Bitmap position;
private Matrix positionMatrix;
private Paint positionPaint;

public MyMapView(Context context) {
    super(context);
    init(context, null);
}

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

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

private void init(final Context context, AttributeSet attrs) {

backgroundMatrix = new Matrix();
backgroundPaint = new Paint();
backgroundPaint.setFilterBitmap(true);

position = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.position);
positionMatrix = new Matrix();

positionPaint = new Paint();
positionPaint.setFilterBitmap(true);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
}

@Override
protected void onDraw(Canvas canvas) {

    int width = getMeasuredWidth();
    int height = getMeasuredHeight();

    if (trackMap!=null)
    {
        Bitmap resizedBitmap = Bitmap.createScaledBitmap(trackMap, height, height, true);
        canvas.drawBitmap(resizedBitmap, backgroundMatrix, backgroundPaint);

    }

        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.translate(xPos-position.getWidth()/2, yPos-position.getHeight()/2);
        canvas.drawBitmap(position, positionMatrix, positionPaint);

        canvas.restore();
}

    public void updatePosition(int xpos, int ypos, Bitmap trackImage)
    {
        xPos=xpos;
        yPos=ypos;
        trackMap = trackImage;
        invalidate();
    }
}

1
你的自定义视图是从哪里继承而来的?你确定你在构造函数中正确处理了参数吗? - Mathias Conradt
你使用FrameLayout的特殊原因是什么?TextView需要显示在View的顶部吗? - Octavian Helm
1
是的,FrameLayout 不允许你这样做。它只是用于容纳单个视图。如果你添加了更多的内容,它将会表现出你所提到的行为,它只是通过固定在左上角来垂直堆叠元素。 http://developer.android.com/reference/android/widget/FrameLayout.html - plainjimbo
6个回答

430

我们可以通过设置子视图的layout_gravity属性来使视图在FrameLayout中居中对齐。

在XML中:

android:layout_gravity="center"
在Java代码中:
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;

注意:使用FrameLayout.LayoutParams而不是其他现有的LayoutParams。


121
这应该成为被接受的答案。其他的回答改变了问题而不是回答它。 - Muz
为什么这个解决方案对我无效。在FrameLayout的中心添加ImageView。cap = new ImageView(CameraActivity.this); LayoutParams params2 = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); params2.gravity=Gravity.CENTER; cap.setLayoutParams(params2); cameraView.addView(cap); - Akanksha Rathore
9
现在它对我有用了。我的错误是我导入了错误的包。经过4个小时的努力,我发现我的错误,实际应该导入的包是android.widget.FrameLayout.LayoutParams; - Akanksha Rathore
2
@Akanksha 那是唯一正确的答案 :) 你们必须使用 FrameLayout.LayoutParams 来将一个视图居中到 FrameLayout 中。 - hector6872

45

我建议使用RelativeLayout而不是FrameLayout。

假设您希望TextView始终在ImageView下方,我会使用以下布局。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerInParent="true"
        android:src="@drawable/icon"
        android:visibility="visible"/>
    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_below="@id/imageview"
        android:gravity="center"
        android:text="@string/hello"/>
</RelativeLayout>
请注意,如果您将元素的visibility设置为gone,则该元素占用的空间也会消失,而当您使用invisible时,则会保留其占用的空间。
如果您想让TextView位于ImageView之上,则只需忽略android:layout_alignParentTop或将其设置为false,并在TextView上忽略android:layout_below="@id/imageview"属性。像这样。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="false"
        android:layout_centerInParent="true"
        android:src="@drawable/icon"
        android:visibility="visible"/>
    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="@string/hello"/>
</RelativeLayout>

我希望这是你在寻找的内容。


你的解释看起来非常好,应该适用于我的情况,但实际上并没有。在我的RelativeLayout中,我有比我说的更多:2个自定义视图、一个LinearLayout、一个Button和一个TextView。有趣的是,除了我的自定义视图之外,其他所有东西都能正常工作,而另一个自定义视图也不受影响,因为它具有fill_parent属性。但是,我正在努力查看是否有遗漏的地方。谢谢。 - Alin
只有在为您的ImageView指定src时,此功能才能按预期工作。如果您试图将文本(或按钮或其他任何内容)放置在稍后将被填充的ImageView下方,则会遇到一些问题,因为直到onResume()完成后,您才能知道按钮或其他任何内容的大小。 - user153275
4
尽可能避免使用RelativeLayout布局。每个RelativeLayout需要进行两次测量——因此嵌套的RelativeLayout具有指数级的测量时间。每当您添加一个新的嵌套RelativeLayout时,测量时间就会加倍。 - Martin Konecny
不能是正确答案,这只是对问题的一种变通方法。 - andrea.rinaldi
请查看下面答案的评论,我完全同意并认为:“这个‘答案’改变了问题而不是回答它”。我们经常看到这种类型的回应,回应离题,并改变了原帖的意图。这种“非回应”不应该被视为本站可接受的行为。 - user2587965
显示剩余2条评论

9

按照以下顺序操作

您可以在FrameLayout中居中任意数量的子元素。

<FrameLayout
    >
    <child1
        ....
        android:layout_gravity="center"
        .....
        />
    <Child2
        ....
        android:layout_gravity="center"
        />
</FrameLayout>

因此关键是

在子视图中添加android:layout_gravity="center"

例如:

我将一个自定义视图(CustomView)和一个文本视图(TextView)居中放置在一个FrameLayout上,像这样:

代码:

<FrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
    <com.airbnb.lottie.LottieAnimationView
        android:layout_width="180dp"
        android:layout_height="180dp"
        android:layout_gravity="center"
        app:lottie_fileName="red_scan.json"
        app:lottie_autoPlay="true"
        app:lottie_loop="true" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textColor="#ffffff"
        android:textSize="10dp"
        android:textStyle="bold"
        android:padding="10dp"
        android:text="Networks Available: 1\n click to see all"
        android:gravity="center" />
</FrameLayout>

结果:

在这里输入图片描述


1
这是唯一对我有效的答案。我有一个包含一个TextureView和两个SurfaceView的FrameLayout。通过这种方式(以及在Surface上使用setZOrderOnTop(true);),我终于将所有内容居中重叠。 - Xavi
这才是真正的答案。谢谢。 - undefined

1

将控件的layout_gravity属性设置为'center_horizontal'和'center_vertical'或者只设置为'center',以使其居中显示。

    <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MovieActivity"
    android:id="@+id/mainContainerMovie"
    >


    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#3a3f51b5"
       />

    <ProgressBar
        android:id="@+id/movieprogressbar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal" />
</FrameLayout>

0
根据https://dev59.com/eW855IYBdhLWcg3w-JbS#13025031,我成功将TabLayout居中于FrameLayout中。

enter image description here

final TabLayout tabLayout = new TabLayout(this);
// Configure TabLayout...
final FrameLayout tabLayoutContainer = new FrameLayout(this);
tabLayoutContainer.setBackgroundColor(Color.RED);

final FrameLayout.LayoutParams tabLayoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
                dpToPx(28));
final FrameLayout.LayoutParams containerLayoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
                dpToPx(48));


tabLayoutParams.gravity = Gravity.CENTER;
tabLayoutContainer.setLayoutParams(containerLayoutParams);
tabLayoutContainer.addView(tabLayout, tabLayoutParams);

0

要在Framelayout中居中一个视图,有一些可用的技巧。我为我的Webview和Progressbar使用的最简单的方法(与您的两个对象布局非常相似),我只需添加android:layout_gravity="center"

这是完整的XML,以防其他人需要做同样的事情

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".WebviewPDFActivity"
    android:layout_gravity="center"
    >
    <WebView
        android:id="@+id/webView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"

        />
    <ProgressBar
        android:id="@+id/progress_circular"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:visibility="visible"
        android:layout_gravity="center"
        />


</FrameLayout>

这是我的输出

screenshot


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接