Android überlagern eine Ansicht über alles?

75

Können Sie eine Ansicht über alles in Android überlagern?

In iPhone würde ich die neue Ansicht frame.originauf (0,0) und ihre Breite und Höhe auf die Breite und Höhe von setzen lassen self.view. Das Hinzufügen zu self.viewwürde dann dazu führen, dass es als Überlagerung fungiert und den Inhalt dahinter abdeckt (oder wenn es einen transparenten Hintergrund hat, wird die Ansicht dahinter angezeigt).

Gibt es eine ähnliche Technik in Android? Mir ist klar, dass die Ansichten leicht unterschiedlich sind (es gibt drei Arten (oder mehr ...) Relativlayout, Linearlayout und Framelayout), aber gibt es eine Möglichkeit, eine Ansicht wahllos über alles zu legen?

Thomas Clayson
quelle

Antworten:

101

Verwenden Sie einfach RelativeLayoutoder FrameLayout. Die letzte untergeordnete Ansicht überlagert alles andere.

Android unterstützt ein Muster, das Cocoa Touch SDK nicht unterstützt: Layoutverwaltung.
Layout für iPhone bedeutet, alles absolut zu positionieren (abgesehen von einigen Dehnungsfaktoren). Layout in Android bedeutet, dass Kinder in Beziehung zueinander gestellt werden.

Beispiel (der zweite EditText deckt den ersten vollständig ab):

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/root_view">

    <EditText
        android:layout_width="fill_parent"
        android:id="@+id/editText1"
        android:layout_height="fill_parent">
    </EditText>

    <EditText
        android:layout_width="fill_parent"
        android:id="@+id/editText2"
        android:layout_height="fill_parent">
        <requestFocus></requestFocus>
    </EditText>

</FrameLayout>

FrameLayoutist eine Art Ansichtsstapel. Gemacht für besondere Fälle.

RelativeLayoutist ziemlich mächtig. Sie können Regeln definieren, z. B. Ansicht A muss das übergeordnete Layout unten ausrichten , Ansicht B muss A unten nach oben ausrichten usw.

Update basierend auf Kommentar

Normalerweise setzen Sie den Inhalt mit setContentView(R.layout.your_layout)in onCreate(es wird das Layout für Sie aufblasen). Sie können das manuell machen und anrufen setContentView(inflatedView), es gibt keinen Unterschied.

Die Ansicht selbst kann eine einzelne Ansicht (wie TextView) oder eine komplexe Layouthierarchie sein (verschachtelte Layouts, da alle Layouts selbst Ansichten sind).

Nachdem Sie setContentViewIhre Aktivität aufgerufen haben, wissen Sie, wie ihr Inhalt aussieht, und Sie können (FrameLayout) findViewById(R.id.root_view)jede Ansicht in dieser Hierarchie abrufen (allgemeines Muster (ClassOfTheViewWithThisId) findViewById(R.id.declared_id_of_view)).

Knickedi
quelle
Ah danke für das Beispiel. Ich vermute also, dass in einer Aktivität die Inhaltsansicht wahrscheinlich ein Framelayout ist? Wenn ich a verwende layoutinflater, um eine relativelayoutaus einer Layout-XML-Datei abzurufen, wie kann ich sie der Inhaltsansicht hinzufügen? Gibt es eine Möglichkeit, einen Verweis auf die Inhaltsansicht zu erhalten? Vielen Dank
Thomas Clayson
Ich habe meine Antwort aktualisiert, damit erklärt wird, was der Inhalt einer Aktivität ist und wie man damit interagiert.
Knickedi
Brillant. Vielen Dank. :)
Thomas Clayson
1
Ich möchte darauf hinweisen, dass ich es FrameLayoutaufgrund seines geringen Gewichts bevorzuge , aber die maximal gemessene Höhe (auch bekannt als seine eigene resultierende Höhe) im Falle einer match_parentGröße nicht an seine Kinder weitergibt, siehe hier . Wenn Sie Android 2 unterstützen und mit Android 2 arbeiten match_parent, RelativeLayoutist dies die einzige funktionierende Option. Ein Beispiel finden Sie hier .
Klassenstapler
JFYI: Bei Android 4.4.4 hat es für mich gereicht, ein Fragment als Overlay zu platzieren. Seit Android 5.0 wurden einige Elemente wie Schaltflächen und Kartenansichten oben platziert. Mit der Lösung in der Antwort funktioniert es wie ein Zauber.
Ray
16
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<LinearLayout
    android:id = "@+id/Everything"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <!-- other actual layout stuff here EVERYTHING HERE -->

   </LinearLayout>

<LinearLayout
    android:id="@+id/overlay"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="right" >
</LinearLayout>

Jetzt wird jede Ansicht, die Sie unter LinearLayout mit hinzufügen android:id = "@+id/overlay", als Überlagerung mit Schwerkraft = direkt im linearen Layout mit angezeigt android:id="@+id/Everything"

Dilroop Singh
quelle
10

Sie können verwenden bringToFront:

    View view=findViewById(R.id.btnStartGame);
    view.bringToFront();
Ahmad Aghazadeh
quelle
9

Der beste Weg ist ViewOverlay Seit Android JellyBeanMR2 (Api 18) können Sie jeder Ansicht jedes Drawable als Overlay als Overlay hinzufügen.

In mMyDrawablezu mMyViewals Overlay:

mMyDrawable.setBounds(0, 0, mMyView.getMeasuredWidth(), mMyView.getMeasuredHeight())
mMyView.getOverlay().add(mMyDrawable)
Jacks Gong
quelle
Tippfehler: mMyDrawable.setBounds
yk4ever
Vielen Dank für Ihre Lösung. Sie können jedoch über das Bild auf Ansichtskomponenten zugreifen. Wenn Ihre Ansicht beispielsweise eine Schaltfläche enthält, wenn Sie auf das Bild klicken, wird automatisch auf die Schaltfläche für die ursprüngliche Ansicht geklickt.
Ranjith Subramaniam
@RanjithSubramaniam Ja, da es nur über die Ansicht gezeichnet werden kann.
Jacks Gong
Aber es wird nicht funktionieren, wenn eine Ansicht auf eine andere gelegt werden muss, da eine Zeichnung nur eine Grafik ist
Neeraj Sewani
0

Ich habe die Markisen schon einmal ausprobiert, aber das hat nicht funktioniert. Jetzt habe ich nur ein LinearLayout anstelle eines TextureView verwendet, jetzt funktioniert es ohne Probleme. Hoffe, es hilft einigen anderen, die das gleiche Problem haben. :) :)

    view = (LinearLayout) findViewById(R.id.view); //this is initialized in the constructor
    openWindowOnButtonClick();

public void openWindowOnButtonClick()
{
    view.setAlpha((float)0.5);
    FloatingActionButton fb = (FloatingActionButton) findViewById(R.id.floatingActionButton);
    final InputMethodManager keyboard = (InputMethodManager) getSystemService(getBaseContext().INPUT_METHOD_SERVICE);
    fb.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            // check if the Overlay should be visible. If this value is false, it is not shown -> show it.
            if(view.getVisibility() == View.INVISIBLE)
            {
                view.setVisibility(View.VISIBLE);
                keyboard.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
                Log.d("Overlay", "Klick");
            }
            else if(view.getVisibility() == View.VISIBLE)
            {
                view.setVisibility(View.INVISIBLE);
                keyboard.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);
            }
HaxnHarald
quelle
1
Ich denke, um dies zu einer wirklich hilfreichen Antwort zu machen, sollten Sie etwas mehr hinzufügen. Beispielcode, Screenshots, ...
GhostCat
0

Ich habe gerade eine Lösung dafür gefunden. Ich habe dafür eine Bibliothek erstellt, um dies auf wiederverwendbare Weise zu tun. Deshalb müssen Sie in Ihrem XML nicht neu codieren. Hier finden Sie eine Dokumentation zur Verwendung in Java und Kotlin . Initialisieren Sie es zunächst von einer Aktivität aus, von der aus Sie die Überlagerung anzeigen möchten.

AppWaterMarkBuilder.doConfigure()
                .setAppCompatActivity(MainActivity.this)
                .setWatermarkProperty(R.layout.layout_water_mark)
                .showWatermarkAfterConfig();

Dann können Sie es von überall in Ihrer App ausblenden und anzeigen -

  /* For hiding the watermark*/
  AppWaterMarkBuilder.hideWatermark() 

  /* For showing the watermark*/
  AppWaterMarkBuilder.showWatermark() 

Gif Vorschau -

Vorschau

Gk Mohammad Emon
quelle