Die Android-Center-Ansicht in FrameLayout funktioniert nicht

81

Ich habe ein FrameLayout, in dem ich zwei Steuerelemente habe: - eine benutzerdefinierte Ansicht, in der ein Bild und Text darauf gezeichnet werden - eine Textansicht mit einem Text

Ich möchte beide im FrameLayout zentrieren, aber ich kann es nicht schaffen. Die Texview ist gut zentriert, meine Cusom-Ansicht bleibt auf der linken Seite, wenn ich sie sichtbar mache.

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

Für Mathias mache ich nichts im Konstruktor, es ist einfach

   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();
    }
}
Alin
quelle
1
Woher kommt Ihre benutzerdefinierte Ansicht? Sicher, dass Sie die Parameter in Ihrem Konstruktor verarbeiten?
Mathias Conradt
Gibt es einen besonderen Grund, warum Sie ein FrameLayout verwenden müssen, und soll die Textansicht über der Ansicht angezeigt werden?
Octavian A. Damiean
1
Ja, das FrameLayout lässt Sie das nicht zu. Es ist wirklich nur für eine einzelne Ansicht. Wenn Sie mehr hinzufügen, als es genau das von Ihnen erwähnte Verhalten aufweist, werden einfach Elemente in einem vertikalen Stapel hinzugefügt, indem Sie sie oben links anheften. developer.android.com/reference/android/widget/FrameLayout.html
plainjimbo

Antworten:

40

Ich würde ein RelativeLayout anstelle eines FrameLayout vorschlagen.

Angenommen, Sie möchten, dass die Textansicht immer unter der Bildansicht liegt, würde ich das folgende Layout verwenden.

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

Beachten Sie, dass, wenn Sie das visibilityeines Elements auf setzen, goneder Speicherplatz, den dieses Element belegen würde, weg ist, während bei Verwendung invisiblestattdessen der Speicherplatz, den es verbrauchen würde, erhalten bleibt.

Wenn Sie möchten, dass die Textansicht über der Bildansicht liegt, lassen Sie das Attribut einfach weg android:layout_alignParentTopoder setzen Sie es auf falseund in der Textansicht lassen Sie das android:layout_below="@id/imageview"Attribut weg . So was.

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

Ich hoffe, das haben Sie gesucht.

Octavian A. Damiean
quelle
Ihre Erklärung sieht sehr gut aus und sollte in meinem Fall funktionieren, tut es aber nicht. In meinem RelativeLayout habe ich mehr als gesagt: 2 benutzerdefinierte Ansichten, ein LinearLayout, eine Schaltfläche und eine Textansicht. Was ist merkwürdig, dass alles funktioniert, außer meiner benutzerdefinierten Ansicht. Die andere benutzerdefinierte Ansicht wird nicht beeinflusst, da sie als fill_parent-Attribute vorliegt. Aber ich versuche zu sehen, ob ich etwas verpasst habe. Danke dir.
Alin
Was ist der Zweck Ihrer benutzerdefinierten Ansicht?
Octavian A. Damiean
Ich habe den gesamten Code der benutzerdefinierten Ansicht zu der Frage hinzugefügt. Zeichnet grundsätzlich ein großes Bild als Hintergrund und ein kleineres an der x, y-Position.
Alin
Dies funktioniert nur wie erwartet, wenn Sie in Ihrer ImageView einen Quellcode angeben. Wenn Sie versuchen, Text (oder Schaltflächen oder was auch immer) unter eine ImageView zu setzen, die später ausgefüllt wird, treten Probleme auf, da Sie die Größe Ihrer Schaltflächen oder was auch immer erst lange nach onResume (. ) hat beendet.
4
Sie möchten RelativeLayouts nach Möglichkeit vermeiden. Jedes RelativeLayout erfordert 2 Messdurchgänge - daher haben verschachtelte RelativeLayouts eine exponentielle Messzeit. Jedes Mal, wenn Sie ein neues verschachteltes RelativeLayout hinzufügen, verdoppelt sich Ihre Messzeit.
Martin Konecny
382

Wir können eine Ansicht in der Mitte von ausrichten, FrameLayoutindem wir die Ansicht layout_gravityder untergeordneten Ansicht festlegen.

In XML:

android:layout_gravity="center"

Im Java-Code:

FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;

Hinweis: Verwenden Sie FrameLayout.LayoutParamsnicht die anderen vorhandenen LayoutParams

userrp1519825
quelle
107
Dies sollte die akzeptierte Antwort sein. Der andere ändert die Frage, anstatt sie zu beantworten.
Muz
Y diese Lösung hat bei mir nicht funktioniert. Hinzufügen von Imageview in der Mitte von Frame layout.cap = new ImageView (CameraActivity.this); LayoutParams params2 = neue LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params2.gravity = Gravity.CENTER; cap.setLayoutParams (params2); cameraView.addView (Kappe);
Akanksha Rathore
8
Jetzt hat es für mich funktioniert. Mein Fehler war, dass ich falsches Paket importiert wurde. Nach 4 Stunden habe ich den Fehler bekommen, dass das tatsächliche Paket android.widget.FrameLayout.LayoutParams importieren sollte;
Akanksha Rathore
2
@Akanksha, das ist die einzig richtige Antwort :) Ihr müsst FrameLayout.LayoutParams verwenden, um eine Ansicht in FrameLayout zu zentrieren.
hrules6872
4

Folgen Sie einfach dieser Reihenfolge

Sie können eine beliebige Anzahl von Kindern in einem zentrieren FrameLayout.

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

Der Schlüssel ist also

Hinzufügen android:layout_gravity="center"der untergeordneten Ansichten.

Beispielsweise:

Ich zentrierte ein Custom und ein Textview auf einem FrameLayoutwie diese

Code:

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

Ergebnis:

Geben Sie hier die Bildbeschreibung ein

Rohit Singh
quelle
1
Dies war die einzige Antwort, die für mich funktioniert hat. Ich habe eine FrameLayout, die eins TextureViewund zwei enthält SurfaceView. Mit diesem (und dem setZOrderOnTop(true);auf den Oberflächen habe ich endlich alles überlagert
Xavi
1

Setzen Sie 'center_horizontal' und 'center_vertical' oder einfach 'center' des Attributs layout_gravity des Widgets

    <?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. Vala
quelle
0

Um eine Ansicht in Framelayout zu zentrieren, stehen einige Tricks zur Verfügung. Die einfachste, die ich für meine Webansicht und meine Fortschrittsanzeige verwendet habe (sehr ähnlich zu Ihrem Layout mit zwei Objekten), habe ich gerade hinzugefügtandroid:layout_gravity="center"

Hier finden Sie vollständiges XML für den Fall, dass jemand anderes dasselbe tun muss

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

Hier ist meine Ausgabe

Bildschirmfoto

Abdul Rehman
quelle