Центральный вид Android в FrameLayout не работает


83

У меня есть FrameLayout, в котором у меня есть 2 элемента управления: - настраиваемое представление, которое рисует изображение и некоторый текст на нем - текстовое представление с текстом

Я хочу центрировать оба объекта в FrameLayout, но мне это не удается. Texview отцентрирован просто отлично, мой пользовательский вид остается с левой стороны, когда я делаю его видимым.

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

Для Матиаса я ничего не делаю в конструкторе, это просто

   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
Откуда расширено ваше пользовательское представление? Уверены, что вы обрабатываете параметры в своем конструкторе?
— Матиас Конрад,

Есть ли какая-то особая причина для использования FrameLayout и должен ли TextView отображаться поверх View?
— Октавиан А. Дамиан

1
Да, FrameLayout не позволит вам этого сделать. Это действительно просто для единого просмотра. Если вы добавите к нему больше, чем это, он будет иметь точное поведение, о котором вы упоминаете, он просто добавляет элементы в вертикальный стек, закрепляя их в верхнем левом углу. developer.android.com/reference/android/widget/FrameLayout.html
— plainjimbo

Ответы:


42

Я бы предложил 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. Но я пытаюсь понять, не упустил ли я что-нибудь. Спасибо.
— Алин

Какова цель вашего пользовательского представления?
— Октавиан А. Дамиан

Я добавил весь код настраиваемого представления на вопрос. В основном рисует большое изображение в качестве фона, а меньшее - в позиции x, y.
— Алин

Это работает, как ожидалось, только если вы укажете src для своего ImageView. Если вы пытаетесь поместить текст (или кнопки или что-то еще) под ImageView, который будет заполнен позже, вы столкнетесь с некоторыми проблемами, потому что вы не сможете узнать размер своих кнопок или чего-то еще до тех пор, пока не будет onResume ( ) закончил.

4
По возможности следует избегать использования RelativeLayouts. Для каждого RelativeLayout требуется 2 прохода измерения, поэтому вложенные RelativeLayout имеют экспоненциальное время измерения. Каждый раз, когда вы добавляете новый вложенный RelativeLayout, время измерения удваивается.
— Мартин Конечны

387

Мы можем выровнять вид по центру FrameLayout, установив layout_gravityдочернее представление.

В 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


108
Это должен быть принятый ответ. Другой меняет вопрос, а не отвечает на него.
— Муз

У меня это решение не сработало. Добавление Imageview в центре Frame layout.cap = new ImageView (CameraActivity.this); LayoutParams params2 = новый LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params2.gravity = Gravity.CENTER; cap.setLayoutParams (params2); cameraView.addView (шапка);
— Akanksha Rathore

8
Теперь это сработало для меня. Моя ошибка заключалась в том, что я импортировал неправильный пакет. Через 4 часа я понял, что должен импортировать фактический пакет android.widget.FrameLayout.LayoutParams;
— Akanksha Rathore

2
@Akanksha, это единственный правильный ответ :) вы, ребята, должны использовать FrameLayout.LayoutParams для центрирования представления в FrameLayout.
— hrules6872

5

Просто следуйте этому порядку

Вы можете центрировать любое количество детей в файле 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
Это был единственный ответ, который у меня сработал. У меня FrameLayoutесть один TextureViewи два SurfaceView. С этим (и setZOrderOnTop(true);на Surfaces я, наконец, все сосредоточил наложение
— Xavi

1

Установите center_horizontal и center_vertical или просто center для атрибута layout_gravity виджета

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

Для центрирования вида в 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>

Вот мой результат

Скриншот

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.