Вигляд центру 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
Звідки поширюється ваш власний вигляд? Ви впевнені, що обробляєте параметри у своєму конструкторі?
Mathias Conradt

Чи є якась особлива причина, за якою вам доводиться використовувати FrameLayout, а TextView відображатиметься у верхній частині подання?
Октавіан А. Дамієн

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, кнопка та TextView. Цікаво, що все працює, окрім мого власного подання. На інший спеціальний вигляд не впливає, оскільки він є атрибутом fill_parent. Але я намагаюся зрозуміти, чи не пропустив я чогось. Дякую.
Алін

Яка мета вашого користувацького перегляду?
Октавіан А. Дамієн

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

Це працює лише за очікуванням, якщо ви вказали src для свого ImageView. Якщо ви намагаєтеся розмістити текст (або кнопки або що завгодно) під ImageView, який буде заповнений пізніше, ви зіткнетеся з деякими проблемами, оскільки ви не зможете дізнатися розмір ваших кнопок або що завгодно до того, як після onResume ) закінчив.

4
Ви хочете уникати RelativeLayouts, де це можливо. Кожен RelativeLayout вимагає 2 проходів вимірювання - тому вкладені RelativeLayouts мають експоненціальний час вимірювання. Щоразу, коли ви додаєте новий вкладений RelativeLayout, ваш час вимірювання подвоюється.
Martin Konecny

384

Ми можемо вирівняти вигляд у центрі 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


107
Це має бути прийнятою відповіддю. Інший змінює питання, а не відповідає на нього.
Муз

Y це рішення для мене не спрацювало. Додавання 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);на Поверхнях я нарешті все сконцентрував накладення
Хаві,

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.