0

Ich befülle ein Layout, um es auf dem Bildschirm anzuzeigen. Jetzt möchte ich dieses Layout teilweise vom Bildschirm verschieben. Ich habe das mit .animate().translationX(-500) auf dem überhöhten Layout versucht. Es bewegte sich außerhalb des Bildschirms genau, wie ich es wollte aussehen:Bewegen von aufgeblasenem Layout/Ansicht an einer neuen Position auf eine animierte Art und Weise

Bevor:

before moving

Nach:

after moving

Aber jetzt habe ich das Problem, dass die Bereich, den das Layout ursprünglich belegt hat, ist nicht anklickbar (z. B. kann nur zwischen Homescreens wischen) arbeitet außerhalb des blau markierten Bereichs).

not clickable area

Wie kann ich lösen, dass, so blauer Bereich ist anklickbar nach dem Umzug, aber der remaing Bereich des Layout (roten Bereichs) könnte noch Klicks registrieren (zB wenn ich es wollte, um zurück mit einem onClickListener)? Ich denke, ich muss mit updateViewLayout() Funktion der windowManager arbeiten, aber ich weiß nicht, was ich bezüglich der Parameter ändern sollte.

Edit 1:

Hier ist der Code. Die Übersetzung wird durch den Button ausgelöst:

overlay.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="horizontal" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#d8ff0000" 
    android:weightSum="1"> 

    <RelativeLayout 
     android:layout_width="match_parent" 
     android:layout_height="245dp"> 

     <TextView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:textAppearance="?android:attr/textAppearanceLarge" 
      android:text="Lorem ipsum " 
      android:id="@+id/textView6" 
      android:layout_marginLeft="10dp" /> 

     <Button 
      android:layout_width="55dp" 
      android:layout_height="wrap_content" 
      android:text="X" 
      android:id="@+id/button" 
      android:layout_gravity="center_horizontal|top" 
      android:layout_alignParentTop="true" 
      android:layout_toEndOf="@+id/textView6" 
      android:layout_marginStart="27dp" /> 
    </RelativeLayout> 
</LinearLayout> 

Dienst, die das Layout aufbläst:

OverlayService.java

public class FloatingMenu extends Service{ 

    private WindowManager wm; 
    private LinearLayout ll; 
    private boolean isPushedToSide = true; 


    @Nullable 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 

     wm = (WindowManager) getSystemService(WINDOW_SERVICE); 
     ll = new LinearLayout(this); 


     LinearLayout.LayoutParams llParameters = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); 
     ll.setBackgroundColor(Color.argb(50, 255, 255, 255)); 
     ll.setLayoutParams(llParameters); 

     final WindowManager.LayoutParams parameters = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); 

     parameters.gravity = Gravity.LEFT | Gravity.TOP; 

     LayoutInflater li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); 
     ll = (LinearLayout) li.inflate(R.layout.overlay, null); 
     final Button b = (Button) ll.findViewById(R.id.button); 
     b.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       if (isPushedToSide) { 
        ll.animate().translationX(0); 
        isPushedToSide = false; 
       }else { 
        ll.animate().translationX(-450); 
        isPushedToSide = true; 
       } 
      } 
     }); 
     wm.addView(ll, parameters); 
    } 
} 

Edit 2:

Während meiner Forschung fand ich heraus, dass .animate().translationX() nur die Position verschiebt, wo die Ansicht gerendert wird und nicht die Ansicht selbst. Das erklärt auch, warum nach der Verwendung von .animate().translationX() das onclick-Ereignis immer noch an der gleichen Position ausgelöst wird, wie vor dem "Verschieben" des Layouts.

Jetzt muss ich eine Möglichkeit finden, die tatsächliche Ansicht zu meiner gewünschten Position zu verschieben, die mit einer Animation kombiniert wird. Irgendwelche Ideen, wie man das macht?

bearbeiten 3: ich viele Beiträge mit ähnlichen Problemen gefunden und wenn ich richtig die Lösung für das Problem bin ist ObjectAnimator statt .animate().translationX() verwenden. Ich habe versucht, zu ersetzen, dass ein Teil in meinem Code, so dass die onClickListener sieht nun wie folgt aus:

b.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View view) { 
     if (isPushedToSide) { 
      //ll.animate().translationX(0); 
      ObjectAnimator.ofFloat(ll, "translationX", 0).setDuration(250).start(); 
      isPushedToSide = false; 
     }else { 
      //ll.animate().translationX(-450); 
      ObjectAnimator.ofFloat(ll, "translationX", -450).setDuration(250).start(); 
      isPushedToSide = true; 
     } 
    } 
}); 

ll ist die Linearlayout ich aufgeblasen haben, mit dem Lorem ipsum Text und Button. Wieder funktioniert die Animation selbst, verhält sich aber immer noch genauso. Ich muss immer noch auf die ursprüngliche Position der Taste klicken, um die onClickListener auszulösen und der blaue Bereich ist immer noch nicht anklickbar.

bearbeiten 4:

war der Vorschlag auszuprobieren .invalidate() zu verwenden, um die aktuelle Position zu aktualisieren. Es hat jedoch nicht funktioniert. Ich bin mir nicht sicher, ob es richtig verwendet wurde.

b.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View view) { 
     if (isPushedToSide) { 
      //ll.animate().translationX(0); 
      ObjectAnimator.ofFloat(ll, "translationX", 0).setDuration(250).start(); 
      ll.invalidate(); 
      isPushedToSide = false; 
     }else { 
      //ll.animate().translationX(-450); 
      ObjectAnimator.ofFloat(ll, "translationX", -450).setDuration(250).start(); 
      ll.invalidate(); 
      isPushedToSide = true; 
     } 
    } 
}); 

ich auch versucht, den x-Wert von LayoutParams ändern und ruft wm.updateViewLayou(ll, updatedParameters), was in Ordnung war. Wenn ich das Overlay 100px nach rechts verschoben habe, wird der Bereich, der onClickListener auslöst, ebenfalls um 100px nach rechts geschoben. Das Problem ist, dass ich das Overlay nur innerhalb der Grenzen des eigentlichen Bildschirms bewegen konnte und dass ich es vom Bildschirm entfernen muss. Tied negative Werte, aber das hat auch nicht funktioniert.

Was ich im Wesentlichen brauche, ist eine Schublade Navigation, aber mit einer begrenzten Höhe (zumindest das ist denke ich, was ich brauche). Ich werde sehen, ob ich so etwas richtig machen kann.

Edit 5:

Korrigierte mein Code, so dass .inflate() aufgerufen wird, wenn die Animation beendet hat, aber es verhält sich immer noch die gleiche Art und Weise:

ObjectAnimator anim = ObjectAnimator.ofFloat (ll „translationX ", 0) .setDuration (250);

anim.addListener(new Animator.AnimatorListener() { 

    @Override 
    public void onAnimationStart(Animator animator) {} 

    @Override 
    public void onAnimationEnd(Animator animator) { 
     b.invalidate(); 
     text.invalidate(); 
     frame.invalidate(); 
     ll.invalidate(); 
    } 

    @Override 
    public void onAnimationCancel(Animator animator) {} 

    @Override 
    public void onAnimationRepeat(Animator animator) {} 
}); 
anim.start(); 

Ich habe auch zwei .gifs aufgezeichnet, die das Problem zeigen. Ich setze die gravity auf CENTER auf die zweite. enter image description here enter image description here

Antwort

0

ich den Schöpfer der Führung bat ich um die Schaffung einer solchen SYSTEM_ALERT_WINDOW Fenstern und er half mir aus. Hier

ist der Code:

public class Fw extends Service { 

    private WindowManager wm; 
    private boolean isPushedToSide = true; 


    @Nullable 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    WindowManager.LayoutParams parameters; 
    Button b; 
    View inflating_layout; 
    LayoutInflater li; 
    ValueAnimator animator; 

    @Override 

    public void onCreate() { 
     super.onCreate(); 

     wm = (WindowManager) getSystemService(WINDOW_SERVICE); 

     li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); 
     inflating_layout = li.inflate(R.layout.overlay, null); 

     b = (Button) inflating_layout.findViewById(R.id.button); 

     parameters = new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, PixelFormat.TRANSLUCENT); 
     parameters.gravity = Gravity.LEFT | Gravity.TOP; 

     isPushedToSide = true; 

     b.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View view) { 
       if (isPushedToSide) { 

        isPushedToSide = false; 

        animator = ValueAnimator.ofInt(parameters.x, parameters.x-450); 
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
         @Override 
         public void onAnimationUpdate(ValueAnimator valueAnimator) { 
          int val = (Integer) valueAnimator.getAnimatedValue(); 
          updateView(inflating_layout, val); 

         } 
        }); 
        animator.setDuration(250); 
        animator.start(); 

       } else { 

        animator = ValueAnimator.ofInt(parameters.x, parameters.x+450); 
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
         @Override 
         public void onAnimationUpdate(ValueAnimator valueAnimator) { 
          int val = (Integer) valueAnimator.getAnimatedValue(); 
          updateView(inflating_layout, val); 

         } 
        }); 
        animator.setDuration(250); 
        animator.start(); 


        isPushedToSide = true; 
       } 
      } 
     }); 
     wm.addView(inflating_layout, parameters); 
    } 

    public void updateView(View view, Integer x) { 
     if (view != null) { 
      if (x != null) parameters.x = x; 
      wm.updateViewLayout(view, parameters); 
     } 
    } 
} 

Jetzt ist alles scheint gut zu funktionieren. Nur die gleitende Animation flackert etwas am Bildschirmrand. Mit einer langsameren Geschwindigkeit, z.B. .setDuration(2500) das passiert nicht. Ich weiß nicht, ob es wegen des Emulators oder aus einem anderen Grund ist.

0

denke ich einfache Möglichkeit, dieses Problem zu lösen, ist zu animieren Ändern Eigenschaft „Breite“ statt, das Layout übersetzen.

hoffe, es hilft

+0

Aber würde diese Methode immer noch den gesamten Inhalt des Layouts anzeigen, nur zusammengedrückt, um die neue Breite anzupassen? – 0x1234

+0

ja, es wird die Größe Ihres Layouts ändern, Sie müssen einen Teil Ihres Layouts verstecken? Können Sie bitte das Code-Schnipsel zeigen? Animationsteil – dosssik

+0

Ja, wenn ich nur die width -Eigenschaft ändern würde, würde es nicht gut aussehen, wenn ich später Inhalt hinzufüge. Ich werde meinen Code später zum Start-Post hinzufügen. – 0x1234