Центральный вид 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

userrp1519825
источник
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>
MN. Вала
источник
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>

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

Скриншот

Абдул Рехман
источник