Grafiken universell platzieren

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von Astrachan, 01.06.2012.

  1. Astrachan, 01.06.2012 #1
    Astrachan

    Astrachan Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    2
    Registriert seit:
    31.05.2012
    Hallo Leute

    Vielleicht könnt ihr mir bezüglich eines nervigen Problems helfen. Bei Google habe ich zumindest keine zufriedenstellende Antwort gefunden.

    Also:
    Ich soll aus vielen Grafiken ein komplettes Bild zusammensetzen. Ihr könnt euch das wie ein Ausrüstungsmenü aus einem Rollenspiel vorstellen. Alle Grafiken sind in 2D und bis auf ein paar Ausnahmen statisch (Rotieren und Skalieren kommt vor).

    Das Ding ist jetzt, dass dieses komplette Bild später automatisch auf quasi allen Android-Geräten gut aussehen soll. Es soll die Auflösung und die Pixeldichte berücksichtigt werden und dafür liegen alle Grafiken in zwei verschiedenen Auflösungen vor.

    Selbstverständlich kann man nicht mit festen Pixeln arbeiten. Dafür wird ja die Einheit "dp" empfohlen. Ich möchte nun wissen, wie professionelle Entwickler sowas handhaben. Die density-indipendent-pixel als Einheit lässt ja nur in XML-Layouts verwenden. Allerdings habe ich nach dem LunarLander-Beispiel gearbeitet und zeichne auf einem Canvas im SurfaceView. Ich erzeuge das Drawable-Objekt und platziere die Grafik im Code.
    Nun kann man natürlich Pixel in dp umrechnen, aber ist "dp" überhaupt die Lösung, wenn ich eine Grafik(Position und Größe) auf allen Geräten korrekt darstellen will?
    Woher soll ich wissen, wie weit ich mit dp maximal gehen kann. Die Doku sagt ja:

    • xlarge screens are at least 960dp x 720dp
    • large screens are at least 640dp x 480dp
    • normal screens are at least 470dp x 320dp
    • small screens are at least 426dp x 320dp

    Also muss ich dennoch die Göße bzw. Auflösung eines Geräts herausfiltern.

    Später will ich den Code universal einsetzbar machen. Wie gebe ich am besten die Position und Größe einer Grafik an, in Prozent? Ich weiß ja vorher nichts über Größe, Auflösung und Pixeldichte.

    Es kann aber auch sein, dass ich völlig auf dem Schlauch stehe und irgendwas Fundamentales übersehe. Über jede Hilfe bin ich sehr froh.



    Wen es interessiert, hier der Code, wie ich ein Bild auf allen Geräten darstelle, das den ganzen Schirm ausfüllt:

    Code:
    private int screenHeight = getResources().getDisplayMetrics().heightPixels;
    private int screenWidth = getResources().getDisplayMetrics().widthPixels;
    
    private Drawable bg_interface = getResources().getDrawable(R.drawable.bg_interface);
    private int bgWidth = bg_interface.getIntrinsicWidth();
    private int bgHeight = bg_interface.getIntrinsicHeight();
    
    bg_interface.setBounds(0, 0, 
         (int)(bgWidth*(screenWidth/(float)bgWidth)), 
         (int)(bgHeight*(screenHeight/(float)bgHeight)));
    bg_interface.draw(canvas);
    
     
    Zuletzt bearbeitet: 01.06.2012
  2. BFK, 02.06.2012 #2
    BFK

    BFK Erfahrener Benutzer

    Beiträge:
    160
    Erhaltene Danke:
    10
    Registriert seit:
    08.12.2010
    Hi Astrachan,
    "dp" zu benutzen ist schon richtig, keine Ahnung ob es eine bessere Lösung gibt.
    Ich verstehe dein Problem nicht ganz, aber ich glaub, dass wenn du alles über canvas erstellst und garkeine externe Resourcen, also Bilder, benutzt, dann wird es ja alles automatisch von Android selbst für jeden Display angepasst.

    Wenn du jetzt aber Billder benutzen willst, dann könntest du dir etwas überlegen um deine Bilder zu platzieren ohne die Positionen (der Bilder) zu benutzen.

    Ich selber wollte mal ein paar Bilder auf einer bestimmten Position platzieren. Hatte damals vieles versucht, aber leider habe ich das nie geschafft. Irgendeine Displaygrösse sah einfach nicht gut genug aus.

    Und so wie ich das verstehe, sollen deine Bilder wie eine Art Puzzle platziert werden. Kannst du da nicht einfach ein normales Layout verwenden..?
    z.B. LinearLayout und mit "layout_margins" rumexperementieren..?
     
  3. Sentenza, 02.06.2012 #3
    Sentenza

    Sentenza Erfahrener Benutzer

    Beiträge:
    224
    Erhaltene Danke:
    65
    Registriert seit:
    15.08.2011
    Ich bin selbst Anfänger, entsprechend ist meine Antwort mit Vorsicht zu genießen, aber ich nutze folgende Funktion die ich vor ein paar Wochen irgendwo im Netz gefunden hatte:
    Code:
    public int dipToPixel(int dip) {
            int value = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 
                    (float) dip, getResources().getDisplayMetrics());
            return value;
        }
    Wobei dip wohl dasselbe wie dp ist.
     
    DieGoldeneMitte bedankt sich.
  4. Astrachan, 04.06.2012 #4
    Astrachan

    Astrachan Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    2
    Registriert seit:
    31.05.2012
    @BFK
    Genau, es geht im Prinzip darum, Grafiken punktgenau zu setzen. Meiner Meinung nach kann man Layouts ganz vergessen. Man definiert ja irgendwie nur relative Größen.
    Die Grafiken sollen nicht wirklich puzzle-artig platziert werden, sondern teilweise aufeinander. Sie überlagern sich auch gegenseitig und solche Geschichten, also ein typischer Game-Screen. Wenn sowas mit Layouts überhaupt möglich ist, dann wohl nur mit sehr viel Geduld ;) Layouts sind einfach nicht gemacht für Spiele-Apps.

    Deshalb glaube ich, dass man nicht darum herumkommt, die Position der Grafiken im Code anhand der Daten des Geräts zu errechnen.

    Ich habe mir jetzt aber die AndEngine angeschaut und sie passt sehr gut zu dem, was ich brauche. Man definiert am Anfang ein "Rechteck" (z.B. 480x800), das man mit Grafiken füllt und dieses Rechteck wird dann auf jedem Gerät korrekt skaliert (manchmal mit schwarzen Balken links und rechts). Vielleicht wäre das auch was für dich. Wobei ich mir nicht sicher bin, inwiefern man Androids View-Elemente mit der AndEngine mixen kann. Es ist halt primär eine Spiele-Engine.

    @Sentenza
    Sieht aus wie eine Formel, mit der man einen dp-Wert in reale Pixeleinheit umrechnet. Das kann ich noch kürzer schreiben ;)
    Code:
    public int dipToPixel(int dip) {
            return (int)(getResources().getDisplayMetrics().density*dip);
        }
    
    Wobei ich die dp-Einheit manchmal überhaupt nicht durchblicke. Ein ImageView-Element wird auf zwei Geräten mit gleicher Auflösung, aber unterschiedlicher Pixeldichte zwangsläufig unterschiedlich aussehen, wenn man die Breite und Höhe in dp angibt. Mit der px-Einheit wäre es aber genau richtig. Ich muss da noch etwas Forschungsarbeit leisten ;)
     
    Zuletzt bearbeitet: 04.06.2012
  5. Hagbard235, 04.06.2012 #5
    Hagbard235

    Hagbard235 Android-Experte

    Beiträge:
    481
    Erhaltene Danke:
    60
    Registriert seit:
    09.06.2009
    Ich würde mit Layern arbeiten, alle Bilder gleich groß machen und die nicht benötigten Teile durchsichtig!
    Drawable Resources | Android Developers

    Abschnitt Layer ansehen.

    Da die Images dann immer die selbe Größe haben und immer, wenn nötig, identisch scaliert werden, sollten sie immer richtig liegen.
     
  6. Astrachan, 05.06.2012 #6
    Astrachan

    Astrachan Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    2
    Registriert seit:
    31.05.2012
    @Hagbard235
    Ich habe mir die Layerlists angeschaut, aber wie meinst du das genau mit Bilder gleich groß machen und die nicht benötigten Teile durchsichtig? Und wie hilft mir das beim punktgenauen Platzieren von Grafiken?
    Bei Bedarf kann ich auch etwas genauer beschreiben, was ich vor habe
     
  7. BFK, 05.06.2012 #7
    BFK

    BFK Erfahrener Benutzer

    Beiträge:
    160
    Erhaltene Danke:
    10
    Registriert seit:
    08.12.2010
    Ich glaube bei deinem Fall kommst du nicht weit mit normale Layouts. Das mit der engine hört sich gut an. Weiss zwar nicht wieviel Aufwand du betreiben musst. Muss ich auch mal testen.
     
  8. Hagbard235, 05.06.2012 #8
    Hagbard235

    Hagbard235 Android-Experte

    Beiträge:
    481
    Erhaltene Danke:
    60
    Registriert seit:
    09.06.2009
    Ich glaube ich habe noch nicht ganz verstanden, was du eigentlich machen willst. Geht es dir "nur" um das simple übereinander legen von 2D-Grafiken, oder sollen die hinterher auch noch bewegt oder animiert werden oder was?

    Ich hatte bei deiner obrigen Beschreibung bzgl. "Ausrüsten" eines Rittes in einem Rollenspiel halt etwas ganz simples im Kopf... halt wie die Ebenen in einem Grafik-Programm, dort sind alle Ebenen identisch groß (Größe des Bildes), aber sie werden übereinander gelegt (Layer) die dann von oben nach unten das gesamte Bild ergeben. Dadurch das aber alle Layer die selben Maße haben werden sie alle gleichartig von "Veränderungen" bzgl. Auflösung usw. betroffen sein und immer noch übereinander passen ohne das sie falsch liegen.... verstehst du jetzt was ich meine? Sie brauchen alle nur den identischen "Startpunkt" und liegen dann immer richtig übereinander.
     
  9. BFK, 05.06.2012 #9
    BFK

    BFK Erfahrener Benutzer

    Beiträge:
    160
    Erhaltene Danke:
    10
    Registriert seit:
    08.12.2010
    Soweit ich das verstanden habe, will er seine Bidler perfekt positionieren, also Punktgenau. So ist zum Beispiel ein Bild A in einem kleinem Screen X Einheiten vom Rand entfernt. Genau X Einheiten soll es auch bei einem sehr grossem Bildschirm sein.

    Und genau hier bringen Android Layouts nicht soo viel, weil zum Beispiel bei einem parallelen Gerät der Abstand sicher anders sein wird als bei einem rechteckigen, machmal ist dieser unterschied sichtbar, manchmal nicht.
     
  10. Astrachan, 06.06.2012 #10
    Astrachan

    Astrachan Threadstarter Neuer Benutzer

    Beiträge:
    9
    Erhaltene Danke:
    2
    Registriert seit:
    31.05.2012
    @Hagbard235
    Ich glaube, ich habe verstanden, wie du es meinst. Du meinst, dass jede einzelne Grafik im Prinzip die gleiche Auflösung hat (pixelmäßig), aber nur einen bestimmten Bereich davon ausfüllt. Also müsste in meinem Fall jede Bilddatei die Dimensionen des Bildschirms haben, aber in diesem "Rechteck" nur einen gewissen vordefinierten Platz einnehmen und der Rest des Rechtecks wäre durchsichtig. Würde man die Bilder dann übereinander legen, würde man alle Grafiken sehen, da man durch die durchsichtigen Teile der Layer hindurchsehen könnte.

    Eine gar nicht so unclevere Lösung, aber meine Grafiken haben alle unterschiedliche feste Größen und ich darf sie nicht verändern. Ich habe hier was gemalt um den Vorgang etwas zu veranschaulichen (die echten Grafiken gehören einer Firma, und sicherheitshalber poste ich sie hier lieber nicht).

    [​IMG]

    Grafik1 (960x640): Füllt den Bildschirm quasi aus, es gibt einen Ausschnitt an der linken Seite, welcher durchsichtig ist (Position (0,0)).

    Grafik2 (143x144): wird zur Hälfte von Grafik1 überdeckt, soll sich permanent um die eigene Achse drehen (Position (30,470)).

    Die zweite Grafik ist ein Zahnrad und soll sich, wie gesagt, drehen. Daneben gibt es noch Skalierungen. Insgesamt sollen sich noch viel mehr Grafiken auf Grafik 1 befinden. Unter anderem auch solche, die sich verändern, sobald sie angeklickt werden (Leuchten, um Klick zu signalisieren).
    Ich hoffe, das sprengt nicht den Rahmen des Möglichen :D

    Zumindest ist das möglich mit der AndEngine (gestern die Drehung herausgefunden). Sie skaliert entsprechend und fügt bei Bedarf schwarze Balken an die Ränder. Aber gibt es Android-eigene Lösungen dafür?

    @BFK
    Hier gibt es ein sehr gutes (und vor allem aktuelles) Einsteigertutorial mit der Andengine. Es dauert nicht lange, bis man erste Ergebnisse sieht.
     
    Zuletzt bearbeitet: 06.06.2012
    BFK bedankt sich.
  11. BFK

    BFK Erfahrener Benutzer

    Beiträge:
    160
    Erhaltene Danke:
    10
    Registriert seit:
    08.12.2010
    Danke, werde ich mir mal ansehen, wenn ich mal Zeit hab..!
     

Diese Seite empfehlen