Java "Catch the Button" App für Android

Thaxll'ssillyia

Captain
Registriert
Dez. 2007
Beiträge
3.533
Hallo Community!

Ich bin ja eigentlich Windows-Developer. Allerdings wollt ich mich jetzt mal an die Android-Programmierung rantrauen, um mal die eine oder andere App für mein Smartphone (Galaxy Note) entwickeln zu können.

Alos hab ich Eclipse und die Android-SDK installiert, und wollte gleich zu beginn mal so eine "Catch the Button" App (Android 2.3.3) realisieren (Der Nutzer muss innerhalb von 10-30 Sekunden so oft wie möglich einen Button drücken, der nach jedem Drücken seine Position auf dem Screen verändert).

Mein Code bisher:

import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.os.Bundle;

public class CatchTheButtonActivity extends Activity implements OnClickListener {

private Button catchButton;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

catchButton = (Button) findViewById(R.id.catchButton);
catchButton.setOnClickListener(this);
}

public void onClick(View v)
{

//LayoutParams params = new LayoutParams(10,10);


//catchButton.setLayoutParams(params);

}
}

Die Zeilen in OnClick sind meine bisherigen Versuche, die Position des Button zu verändern.
Allerdings hängt sich dort die App immer auf.
Ich hab nach einer Weile Suchen im Internet festgestellt, das es enorm schwierig sein soll, die Position von Steuerelementen zu verändern. In C#/Java genügt da eine Codezeile. Wie muss es denn hier aussehen?

Vielen Dank für Hilfe!

Gruß Thax
 
Dies ist bei Android in der Tat etwas schwierig.
Das Problem ist, dass Android die Activities mit LayoutManagern zusammenbastelt. Diese Layouts werden dann quasi wie Kacheln aneinandergereiht. Mit einem RelativeLayout hat man zwar mehr Möglichkeiten, zu bestimmen, an welche Position dies platziert werden soll, aber auch hier hat man keine Möglichkeit absolute Werte anzugeben. Das AbsoluteLayout, welches erlaubt, absolute Werte zu benutzen, ist nämlich deprecated.

Es gäbe zwar die Möglichkeit Animationen zu verwenden, aber dies funktioniert erst ab 4.0 richtig, da in den unteren Versionen die Views sich nur optisch verschieben. Logisch bleiben sie nämlich an ihrem alten Platz und auch dort reagiert der OnClick-Listener.

Auf die Schnelle würde mir da nun auch keine Lösung einfallen, höchstens mit irgendwelchen LayoutParams zu arbeiten, wo zufallsbedingt das Margin geändert wird. Allerdings musst du hier aufpassen, da im Code alles in Pixeln angegeben wird. Da die Android-Geräte unterschiedliche Auflösungen haben, wirkt sich das immer anders aus. Hier musst du dann mit dem Skalierungsfaktor arbeiten, welchen du mit
Code:
float density = getResources().getDisplayMetrics().density;
herausfinden kannst.

Android ist für sowas nicht so richtig gedacht, für das, was du vorhast.

edit:
btw. du kannst den OnClick-Listener schon im XML-Layout definieren:
Code:
android:onClick="klickMich"
im Code muss dann folgendes stehen:
Code:
public klickMich(View view)
{ 
   ...
}
wichtig ist, dass sie als public deklariert wurde und die View als Parameter bekommt.
 
Zuletzt bearbeitet:
du könntest mit custom view templates arbeiten und sozusagen immer ein neues view genenieren, dort den button neu platzieren und mit setContentView das aktuelle überschreiben. wie man views zur laufzeit erstellt findest du in den docs.
 
Hier musst du dann mit dem Skalierungsfaktor arbeiten, welchen du mit

float density = getResources().getDisplayMetrics().density;

herausfinden kannst.

Android ist für sowas nicht so richtig gedacht, für das, was du vorhast.

edit:
btw. du kannst den OnClick-Listener schon im XML-Layout definieren:

android: onClick="klickMich"

im Code muss dann folgendes stehen:

public klickMich(View view)
{
...
}

wichtig ist, dass sie als public deklariert wurde und die View als Parameter bekommt.

Aha, dankeschön für die schnelle Hilfe.

ISt ja ärgerlich, dass das so komisch gelöst ist mit dem Layout.
Ich arbeite gerade an den LayoutParams, aber ich steh irgendwie auf dem Schlauch. Wie muss ich diese mit der Density in Verbindung bringen, um auch die Auflösung zu berücksichtigen?
 
Bei Android gibt es nicht nur die Einheit "Pixel" (px), sondern die "Dichteabhängigen Pixeln" (dip).
Diese Einheit wurde in Android extra eingeführt, um auf jedem Display die selbe optische Größe darstellen zu können.
Also z.B. 10dip hat auf jedem Display die selbe optische Größe. 10px hingegeben aber nicht.
Während man im XML-Layout die wahl zwischen den beiden Einheiten hat, gibt es im Code allerdings nur Pixel. Deswegen muss man hier mit den Skalierungsfaktor (Google nennt es Dichte) arbeiten, um die exakte Größe zu berechnen, die man haben möchte. Bei kleineren Geräten ist die Dichte geringer, als bei größeren Geräten.

Ich hab jetzt mal selbst zu diesem Problem recherchiert und bin nun zum folgenden Ergebnis gekommen:

Code:
public void onButtonClicked(View view)
    {     
        MarginLayoutParams marginParams = new MarginLayoutParams(view.getLayoutParams());
        marginParams.setMargins(200, 200, 200, 200);
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
        view.setLayoutParams(layoutParams);
    }

Die Pixeldichte ist hier nicht berücksichtigt worden.
Beim Klicken auf den Button hole ich mir erstmal die Margin-Parameter vom Button. (view ist der Button). Nun setze ich neue Margin-werte ein.
Da der Button sich in einem RelativeLayout befindet erzeuge ich mir neue RelativeLayout-Parameter, mit den neuen Margin-Werte und übergebe sie dann den Button.

Bei meinem Beispiel wird der Button nun um 200 Pixel nach Links, Rechts, Oben und Unten verschoben. Dann musst du es nun mit deinen Werten füllen.
Um von px nach dip zu rechnen, musst du dann den Pixel-wert mit der Dichte multiplizieren.
also z.B.
Code:
float density = getResources().getDisplayMetrics().density;
int px = 200;
int dip = (int) (px * density);
 
Zuletzt bearbeitet:
Mhh, ich habs jetzt mal ausprobiert, allerdings stürzt die App ab, sobald ich den Button drücke.

Inhalt der onClick-Methode:

float density = getResources().getDisplayMetrics().density;
int px = 200;
int dip = (int) (px * density);


MarginLayoutParams marginParams = new MarginLayoutParams(catchButton.getLayoutParams());
marginParams.setMargins(0, 0, 0, dip);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
catchButton.setLayoutParams(layoutParams);

Wieso gibts keinen Einzelschritt-Debugger? Wieso kommen keine Exceptions? Ich komm mir vor wie in der Steinzeit...:(
 
Zuletzt bearbeitet:
Wie wäre es, wenn du einfach ein Rectangle zeichnen lässt (mit Farbe oder Grafik) und dann auf die Touchscreenevents reagierst? Im Endeffekt wird bei Buttons nicht anderes gemacht.
Das Layout ist deswegen so fix, weil es keinen Sinn macht die GUI nachträglich so zu manipulieren. Spiele wären der einzige Grund dafür, und da benutzt man als Spielelemente halt keine GUI-Elemente.
 
Doch, sowas gibt es.
Die Ausgaben werden mittels Logcat in Ecplise angezeigt. Im Manifest muss noch debugable auf true gesetzt werden. Das Logcat-Fenster kannst du folgendermaßen erreichen:
Window -> show view -> other -> Android -> Logcat

Fürs Debuggen gibt es zwei Ansichten:
Window -> show perspektive -> other -> DDMS
Window -> show perspektive -> other -> Debug

In DDMS kannst du die einzelnen Devices sehen. Dort kannst du bei einzelnen Apps den Debug-Mode aktivieren, indem du auf die App klickst und dann auf den grünen Käfer.
Wenn dann ein Haltepunkt erreicht wird, schaltet Eclipse automatisch in die Debug-Ansicht, wo du dann Schritt für Schritt durchgehen kannst.

Man kann auch die App gleich beim Starten in den Debug-Modus starten, indem man in der Java-Ansicht anstatt den "start"-button den "debug"-Button klickt. (links neben start)
 
Zurück
Oben