Grafik Darstellung

  • Antworten:41
  • OffenNicht stickyBentwortet
  • Forum-Beiträge: 28

12.10.2018, 23:03:36 via Website

Hallo,
zurzeit arbeite ich an einer App, über die ich meine Modelleisenbahn steuern kann. Dabei möchte ich angezeigt bekommen, wo sich ein Zug befindet und wie eine Weiche gestellt ist. Dazu habe ich mir einen Gleisplan erstellt, auf dem alle Gleise frei sind und die Weichen nicht eingezeichnet sind. Das ist mein Hintergrund der App. Wenn ein Zug auf einem Gleis steht soll der Gleisabschnitt von gelb auf Rot die Farbe ändern. Dazu habe ich ein View mit der Farbe Rot auf das gelbe Gleis platziert, welches sich bei verschiedenen Größen vom Display verschiebt. Wie kann ich es lösen, dass das View genau auf dem gelben Gleis sich befindet? Oder gibt es eine einfachere Lösung, wie ich das realisieren kann? Außerdem verzerrt sich der Hintergrund bei verschiedenen Displaygrößen. Wie geht es, dass das Hintergrundbild sich nicht verzerrt?
Hier noch ein Screenshot der Appimage

Mfg. PBahner

Diskutiere mit!
Beste Antwort
  • Forum-Beiträge: 487

13.10.2018, 11:32:44 via Website

Ich meinte nicht das du für jede Kombination ein Bild machen sollst.
Sondern du sollst kein Hindergrundbild nehmen .
Du sollst das Bild Programmatisch zur Laufzeit erzeugen mit Grafik Methoden wie Line Zeichner, Kreis, Rechteck, Kreisbogen, so wie eine Vektorgrafik. Nicht in Exel Zeichen und nur anzeigen das wird immer Probleme geben.

Kannst ja Trotzdem ein fertiges Bild in dein Bitmap Laden und nur die Gleis abschnitte darüber zeichnen muss das halt Pixel genau sein so wie im Bild , und dieses Bitmap läst du in deiner View anzeigen.
Denke dafür ist es am besten wenn du von View, ImageView oder was du meinst eine Klasse ableitest und in ihr die onDraw Methode Überschreibst. Und genau dort in das Canvas dein gezeichnetes Bitmap lädst .

Im layout benutzt du dann deine eigene View.

Das währe mein Vorschlag, knapp erklärt.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 487

13.10.2018, 08:30:16 via Website

Hallo wie hast du denn das Bild gemacht?

Ich würde ein Bitmap erstellen Inder passenden Größe und deine Strecken mit Hilfe von canvas Grafik funktionieren auf die bitmap zeichnen. Dann kannst du wenn sich die Farbe eines Abschnittes ändern soll. Einfach diesen Bereich beim neu zeichnen in einer anderen Farbe darstellen.

Oder du baust dir die Grafik aus mehreren drawable zusammen und erstellst die in verschiedenen Farben.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 28

13.10.2018, 09:44:11 via Website

Hallo Jokel
Den Gleisplan habe ich mit Excel erstellt. Dort habe ich dann die Signale als Bilder eingefügt. Ich möchte nicht für jede Veränderung der Farbe ein neues Hintergrund Bild einfügen, da es sonst bis zu über 60 Bilder werden könnten. Die App soll auf verschiedenen Geräten laufen, sodass es viel zu umständlich wäre für jedes Gerät ein Hintergrund Bild mit passender Größe zu erstellen.
Erkläre mir bitte genauer, wie ich aus mehreren drawable eine Grafik zusammen bauen kann.

Hilfreich?
Diskutiere mit!
Beste Antwort
  • Forum-Beiträge: 487

13.10.2018, 11:32:44 via Website

Ich meinte nicht das du für jede Kombination ein Bild machen sollst.
Sondern du sollst kein Hindergrundbild nehmen .
Du sollst das Bild Programmatisch zur Laufzeit erzeugen mit Grafik Methoden wie Line Zeichner, Kreis, Rechteck, Kreisbogen, so wie eine Vektorgrafik. Nicht in Exel Zeichen und nur anzeigen das wird immer Probleme geben.

Kannst ja Trotzdem ein fertiges Bild in dein Bitmap Laden und nur die Gleis abschnitte darüber zeichnen muss das halt Pixel genau sein so wie im Bild , und dieses Bitmap läst du in deiner View anzeigen.
Denke dafür ist es am besten wenn du von View, ImageView oder was du meinst eine Klasse ableitest und in ihr die onDraw Methode Überschreibst. Und genau dort in das Canvas dein gezeichnetes Bitmap lädst .

Im layout benutzt du dann deine eigene View.

Das währe mein Vorschlag, knapp erklärt.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 28

13.10.2018, 12:03:54 via Website

Danke dir!
Die Canvas Klasse mit den "Draw" Methoden kannte ich bisher noch nicht. Ich werde das Mal ausprobieren.(cool)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 28

16.10.2018, 22:46:58 via Website

Hallo,
ich habe jetzt ein bisschen herumprobiert. Als Test habe ich ein Kreuz in meine App gezeichnet. Funktioniert auch gut. Das Problem ist aber, dass die App abstürzt, wenn ich die Activity starte. Wenn ich die Zeilen mit "//" in OnCreate() als Kommentar markiere, Funktioniert es, aber das Menu verschwindet. Was kann ich machen, dass ich meine Linien Zeichnen kann und das Menu zusehen ist?

Hier mein Code der Activity:

public class EstwActivity extends AppCompatActivity {

private static final String LOG_TAG = "EstwApp";

MyCanvas myCanvas;
private View estwV;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_estw);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    estwV = findViewById(R.id.EstwV);

    //FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    //fab.setOnClickListener(new View.OnClickListener() {
    //    @Override
    //    public void onClick(View view) {
    //        Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
    //                .setAction("Action", null).show();
    //    }
    //});

    myCanvas = new MyCanvas(this);
    myCanvas.setBackgroundColor(Color.BLACK);
    setContentView(myCanvas);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    MenuItem itemTrennen = menu.findItem(R.id.item_trennen);
    MenuItem itemVerbinden = menu.findItem(R.id.item_verbinden);

    if (globaleVariablen.getIs_connected() == true) {
        itemTrennen.setVisible(true);
        itemVerbinden.setVisible(false);
    } else {
        itemTrennen.setVisible(false);
        itemVerbinden.setVisible(true);
    }
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (R.id.item_verbinden == item.getItemId()) {
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
    }

    if(R.id.item_trennen == item.getItemId()) {
        trennen();
    }
    return true;
}

public void trennen() {
    if (globaleVariablen.getIs_connected() && globaleVariablen.getStream_out() != null) {
        globaleVariablen.setIs_connected(false);
        Log.d(LOG_TAG, "Trennen: Beende Verbindung");
        try {
            globaleVariablen.getStream_out().flush();
            globaleVariablen.getSocket().close();
            Toast.makeText(this, "Getrennt!", Toast.LENGTH_LONG).show();
        } catch (IOException e) {
            Log.e(LOG_TAG,
                    "Fehler beim beenden des Streams und schliessen des Sockets: "
                            + e.toString());
        }
    } else
        Log.d(LOG_TAG, "Trennen: Keine Verbindung zum beenden " + globaleVariablen.getIs_connected() + " " + globaleVariablen.getStream_out());
}





public class MyCanvas extends View {
    Paint paint = new Paint();

    private void init() {
        paint.setColor(Color.RED);
        paint.setStrokeWidth(7);
    }

    public MyCanvas(Context context) {
        super(context);
        init();
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
        canvas.drawLine(canvas.getWidth(), 0, 0, canvas.getHeight(), paint);
    }
}

}

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 487

17.10.2018, 07:13:36 via Website

Hallo
Das liegt daran das du durch das zweite „setContentView“ dein XML Layout überschreibst. Du schaltest es somit aus als hättest du es nicht geladen. Dadurch existieren auch alle in dem Layout vorhandene ID’s nicht mehr.
setContentView(myCanvas);
setContenView sollte in einer Activity nur ein mal benutz bereden.

Erstens solltest du deine Custem Viev Klasse nicht als Innere Klasse erstellen sondern in einer eigenen Datei.
Zweiten binde deine CustemView Kasse im XML layout ein somit hast du auch weiterhin alle gestalterische Möglichkeiten die dir XML bietet.
Es ist zwar auch möglich es in Java einzubinden finde ich aber Umständlich besonders für Anfänger.

http://www.vogella.com/tutorials/AndroidCustomViews/article.html
https://developer.android.com/guide/topics/ui/custom-components

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 28

17.10.2018, 18:32:08 via Website

Die Klasse "MyCanvas" habe ich jetzt in eine extra Datei verschoben. In der Activity habe ich alles von der "MyCanvas" Klassse entfernt. Jetzt habe ich die Klasse mit
<de.my.bluetoothestw.MyCanvas
android:id="@+id/myCanvas"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

in das xml layout eingebunden. das sieht jetzt so aus:
image
aber auf meinem Handy stürzt die App beim öffnen der Activity ab. Wenn ich das in der xml Datei nicht einbinde, funktioniert es. Was habe ich falsch gemacht, dass die Activity abstürtzt?

— geändert am 17.10.2018, 18:43:51

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 487

17.10.2018, 20:58:31 via Website

Hallo Hilfreich wäre unter anderem wenn du uns das xml Layout auch zeigen würdest .
Bitte die komplette Datei, und wie deine Custom View jetzt aussieht .
Wo blendest du denn das Bild ein?
Auch interesant ist wie du von der Activty auf deine View zugreifst wenn du das überhaupt schon tust.

— geändert am 17.10.2018, 21:18:07

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 28

17.10.2018, 21:51:01 via Website

Hallo
content_estw.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="keine Links auf externe Webseiten"
    xmlns:app="keine Links auf externe Webseiten"
    xmlns:tools="keine Links auf externe Webseiten"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/estw"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="de.my.bluetoothestw.EstwActivity"
    tools:showIn="@layout/activity_estw">

    <de.my.bluetoothestw.MyCanvas
        android:id="@+id/myCanvas"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</android.support.constraint.ConstraintLayout>

activity_estw.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="keine Links auf externe Webseiten"
    xmlns:app="keine Links auf externe Webseiten"
    xmlns:tools="keine Links auf externe Webseiten"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="de.my.bluetoothestw.EstwActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?android:attr/textColorLink"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include
        layout="@layout/content_estw"
        android:layout_height="359dp" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

MyCanvas.java:

public class MyCanvas extends View {
    Paint paint = new Paint();

    private void init() {
        paint.setColor(Color.RED);
        paint.setStrokeWidth(7);
        paint.setAntiAlias(true);
    }

    public MyCanvas(Context context) {
        super(context);
        init();
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), paint);//canvas.height
        canvas.drawLine(canvas.getWidth(), 0, 0, canvas.getHeight(), paint);
    }
}

EstwActivity.java:

public class EstwActivity extends AppCompatActivity {

    private static final String LOG_TAG = "EstwApp";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_estw);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setSubtitle("@string/subtitle_activity_estw");

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        MenuItem itemTrennen = menu.findItem(R.id.item_trennen);
        MenuItem itemVerbinden = menu.findItem(R.id.item_verbinden);

        if (globaleVariablen.getIs_connected() == true) {
            itemTrennen.setVisible(true);
            itemVerbinden.setVisible(false);
        } else {
            itemTrennen.setVisible(false);
            itemVerbinden.setVisible(true);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        if (R.id.item_verbinden == item.getItemId()) {
            Intent intent = new Intent(this, MainActivity.class);
            startActivity(intent);
        }

        if(R.id.item_trennen == item.getItemId()) {
            trennen();
        }
        return true;
    }
}

Das Bild ist nur als Hintergrund eingefügt.
Leider wird bei mir "Um Spam in unserem Forum zu vermeiden, können neue Mitglieder vorerst keine Links auf externe Webseiten veröffentlichen." angezeigt, somit musste ich an manchen stellen "keine Links auf externe Webseiten" schreiben.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 487

17.10.2018, 23:05:03 via Website

Hi
versuche mal

 android:layout_width="0dp"
 android:layout_height="0dp"
 app:srcCompat="?android:attr/panelBackground"
 android:id="@+id/imageView" app:layout_constraintEnd_toEndOf="parent"
 app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"
 app:layout_constraintStart_toStartOf="parent"/>

warum nur wrap_content ? du willst doch das gesamte Bild ausfüllen.
akerpukte sind auch nicht gesetzt.
und ein hindergrund Farbe oder Drawable ist auch nicht gesetz solte bei einer View babei sein.

in der View Klasse soltest du alle drei Kostrucktor verwenden.

public GameZoomView(Context context) {
 super(context);

}
/--------------------------------------------------------------------/
public GameZoomView(Context context, AttributeSet attrs) {
super(context, attrs);

}
/--------------------------------------------------------------------/
public GameZoomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 487

18.10.2018, 08:22:50 via Website

Hallo

Ich würde das etwas anders machen.
Ich würde nicht das Bild als Hindergrund anzeigen denn da wirst du auch wieder Verschiebungen bei unterschiedlichen Geräten Display Auflösungen bekommen.

Das Bild dein GleisLayout wurde ich als Bild in den Assets oder als Drawable mitgeben.
Welche Auflösung musst du entscheiden würde mich an der Display Auflösung orientieren.
In der grösse des Bildes erstellst du nein Bitmap.
Das Bild lädst du aus den assets in das Bitmap. Nun erstellst du ein Canvas aus dem Bitmap.
Jetst kannst du uber das Canvas aub das Bitmap zeichnen.
Wenn du ferig gezeichnet hast kannst du das Bitmap einem im XML Layut erstellten ImagView zum anzeigen Übergeben.
Das geht auch ohne das du eine Klasse ableiten musst..

http://germanylandofinnovation.com/questions/3582/erstellen-einer-leeren-bitmap-und-zeichnen-von-canvas-in-android.html

https://gist.github.com/alvareztech/6627673

https://individuapp.com/softwareentwicklung/android-kurs/assets-ressourcen-lokalisierung/
https://gist.github.com/alvareztech/6627673

— geändert am 18.10.2018, 09:03:52

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 487

18.10.2018, 10:14:52 via Website

Hallo nur mal zu Info man kann hier imForum nur eine Antwort zu besten machen. Wenn dir andere auch gefallen dann Kicke auf gefallen. Wenn du dich mit der besten umentscheidest dann musst du die alte erst zurücknemen.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 28

19.10.2018, 13:02:55 via Website

Hallo
Danke dir! Die App stürtzt nicht mehr ab. Wie kann ich jetzt z.B.: die Farbe der Linie zu einem späteren Zeitpunkt ändern und eine neue Linie zeichnen?

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 28

20.10.2018, 21:01:00 via Website

Hallo
Kann ich dann die Linie wieder Löschen oder muss ich eine neue drüber Zeichnen? Und wie geht das?

— geändert am 20.10.2018, 21:01:39

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 487

21.10.2018, 16:16:34 via Website

Nein Löschen kannst du das nicht. Das ist eine Pixelgrafik .
Entweder wieder drüberzeichen oder das Bild wieder neu laden.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 28

21.10.2018, 16:20:07 via Website

Wie funktioniert das genau. Ich habe bis jetzt nur in die onDraw() Methode drawLine() eingefügt. Funktioniert auch, aber wie kann ich jetzt, wenn etwas auf meiner Anlage passiert, eine neue Linie drüber Zeichnen?

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 487

21.10.2018, 16:31:27 via Website

Für jeden gleisabschnitt würde ich eine Variable erstellen in die aussagt ob das entsprechende stück Rot oder Grün oder transparent werden soll.
Für die gesamte Grafik Ausgabe würde ich eine Methode machen. Als erstes würde ich das Hintergrund Bild in das Bitmap und Cavas laden.
Danach die gleisabschnitte drüber zeichnen mit der Farbe in der dazugehörigen variablen . ist nur Transparent gesetzt wird an der stelle nur der Hintergrund erscheinen.
Diese Methode rufst du nun immer wieder auf wenn sich etwas geändert hat . die Grafik Ausgabe wird somit immer wieder von vorne neu gezeichnet.
Die variablen kannst du nun von deiner Programm Logik aus setze und immer wieder die Grafik Ausgabe neu zeichnen lassen.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 28

21.10.2018, 16:46:54 via Website

Muss die Methode in die MyCanvas Klasse? Und kann ich diese von meiner EstwActivity.java starten?

Hilfreich?
Diskutiere mit!

Empfohlene Artikel