Android (LIRC) Button’s Grafik je nach Status verändern (Dynamische Oberfläche)

Ich habe mich entschlossen neue Kategorie einzuführen: „Android“. Hier kann ich meine gesammelten Erfahrungen mit euch teilen die nicht nur explizit für unsere LIRC Application gelten sondern auch in anderen Projekten verwendet werden können.

Und diesmal gehen wir bisschen mehr auf die Oberfläche unserer APP ein. Welche APP? Solltest du dir gerade diese Frage stellen dann verweise ich dich hierhin : Infrarot (IR) LIRC Android Application für alle anderen gilt weiter geht’s! (Übrigens bin ich zurück zu Eclipse gewechselt, ich komme mit Android Studio einfach nicht klar…)

Ich habe zuerst die APP für die Bedienung meiner Musikanlage programmiert, besonders die Steuerung der Lautstärke war mir besonders wichtig. In diesem Fall haben wir auf einer herkömmlichen Fernbedienung die Möglichkeit die Lautstärke um 1 zu erhöhen bzw. senken und durch festhalten der Taste diese so lange zu erhöhen/senken bis wir die Taste wieder loslassen. Dieses Verhalten musste natürlich auch in die APP übernommen werden am besten in Form selbst gemachter grafischer Button’s oder sonst irgendwelcher Icons (es soll ja schön aussehen). Wie kriegen wie das hin? Und wie verknüpfen wir den Zustand des Buttons mit den entsprechenden LIRC Befehlen?

1.) Oberfläche

Fangen wir doch erstmal mit der Oberfläche an. In unserer Activity hatten wir einen Button erstellt den wir jetzt mal bisschen verändern werden. Zuerst habe ich zwei einfache PNG’s erstellt.

btnbtn_pressed

 

 

 

 

 

Kopiert diese zwei Bilder in den Android Projekt Ordner im Unterverzeichnis (res/drawable-xhdpi). Welchen drawable Ordner ihr braucht hängt von der Auflösung eures Smartphones ab. In meinem Fall war es eben xhdpi. Es ist aber nicht schlimm wenn ihr erstmal diesen Ordner auswählt Android passt die Bilder sowieso automatisch an. Zusätzlich erstellen wir im Ordner „res“ einen neuen Ordner und nennen ihn nur „drawable“. Damit sich die Grafik bei einem Klick auf dem Button ändert müssten wir das „hart“ in die Klasse programmieren. Das brauchen wir aber nicht. Denn Android bietet uns die Möglichkeit ein sogenannten „Selector“ zu erstellen. Ein „Selector“ verwaltet so zu sagen den Status von allen möglichen „drawablen“ Elementen. Dazu brauchen wir kein JAVA Code sondern nur eine einfache XML Datei. Wir erstellen also eine XML Datei (vom Typ Selector) in unserem neu erstellen Verzeichnis „drawable“ und nennen sie „button_change.xml“ (Eclipse -> Drawable -> Rechte Maustaste -> New -> Android XML File).

BS1

Wir machen die erstelle Datei auf und kopieren folgendes in den Selector hinein:

<item android:state_pressed="true"
       android:drawable="@drawable/btn_pressed" /> <!-- pressed -->
<item android:state_focused="true"
       android:drawable="@drawable/btn_pressed" /> <!-- focused -->
<item android:drawable="@drawable/btn" /> <!-- default -->

Ihr sieht wir behandeln dort drei Zustände eines Button’s: Pressed, Focused, Default. Bei gedrücktem und fokussierten Zustand soll das btn_pressed PNG angezeigt werden. Im „default“ Zustand wir das normale PNG angezeigt. Jetzt müssen wir nun noch irgendwie diesen Selector unserem Button in der Activity zuweisen. Und das geht ziemlich einfach. Wir machen unsere Activity auf ändern die Größe des Buttons in gleiche Proportionen (zB. 100 * 100 dp freiwillig), lassen den Text im Button leer und setzen dessen Background auf unseren „Selector“. Am Ende sollte folgendes drin stehen:

<Button
 android:id="@+id/button"
 android:layout_width="100dp"
 android:layout_height="100dp"
 android:layout_centerHorizontal="true"
 android:layout_centerVertical="true"
 android:background="@drawable/change_button"
 android:text="" />

BS2

Nun können wir alles Speichern und die Applikation testen. Jetzt sollte sich der Button ändern abhängig davon ob wir den berühren, festhalten oder wieder loslassen.

2.) LIRC IR Befehle abschicken

Nun müssen wir nur noch den Status des Button’s bei uns im Code abgreifen und entsprechende LIRC Befehle abschicken. Wir haben ja bereits die onClick Methode in unserer MainActivity drin die jeweils immer ein Befehl abschickt wenn wir auf den Button klicken. Jetzt brauchen wir noch die Methode zum festhalten und wieder loslassen des Buttons.

Dazu habe ich zwei zusätzliche Methoden verwendet.

OnTouchListener und OnLongClickListener

Wir implementieren diese aus der Superklasse View in unsere MainActivity und holen die passenden Methoden:

BS3

Zusätzlich erstellen wir eine private boolesche Variable „btnlongpress“ und setzen sie auf false.

private boolean btnlongpress = false;

Lass uns doch erstmal um die OnLongClick Methode kümmern. Diese brauchen wir um zu bestimmen das der Button festgehalten wird. Also schreiben wir folgendes rein:

 @Override
 public boolean onLongClick(View v) {
      switch (v.getId()){
      case R.id.button:
           new Connection().execute("SEND_START TEUFEL KEY_VOLUMEUP");
           btnlongpress = true;
           return true;
      }
      return false;
 }

So beim festhalten des Buttons wird der Befehl SEND_START an LIRC geschickt. Das bedeutet das LIRC nun ständig die angegebene IR Sequenz abschickt bis wir es beenden. Zusätzlich wird unsere „btnlongpress“ Variable auf „true“ gesetzt und die Funktion wird beendet. Nun müssen wir uns um das Beenden des Signals kümmern, sprich wenn der Button losgelassen wird muss entsprechend „SEND_STOP“ zu LIRC geschickt werden. Dafür brauchen wir die zweite Methode:

@Override
public boolean onTouch(View v, MotionEvent event) {
     switch (v.getId()){
     case R.id.button:
          if (event.getAction() == MotionEvent.ACTION_UP){
               if (btnlongpress) {
                    new Connection().execute("SEND_STOP TEUFEL KEY_VOLUMEUP");
                    btnlongpress = false;
               }
          }
     break;
     }
 return false;
 }

Was macht diese Methode? Ganz einfach sie greift auf das MotionEvent des View Elements zurück. Das heißt sobald wir den Button loslassen wird das Event „ACTION_UP“ aufgerufen. Damit wissen wir das wir den „SEND_STOP“ Befehl abschicken müssen. Zusätzlich wird „btnlongpress“ zurück auf „false“ gesetzt. Manche fragen sich wieso man diese Methode nicht für beide Events (ACTION_UP und ACTION_DOWN) verwendet. Damit wäre die OnLongClick Methode überflüssig. Ich benutze es deshalb nicht, weil bei einem Druck auf das Button zwar die Methode aufgerufen wird mit dem Event „ACTION_DOWN“ aber beim loslassen wird sie nicht nochmal aufgerufen.

Am Ende sollte nun folgendes drin stehen:

BS4

Ich denke damit lassen sich schöne LIRC Anwendungen programmieren.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.