Simples 2-Spalten-Layout: Wie geht das?

  • 9 Antworten
  • Neuester Beitrag
Diskutiere Simples 2-Spalten-Layout: Wie geht das? im Android App Entwicklung im Bereich Betriebssysteme & Apps.
S

Schranz0r_23

Neues Mitglied
Mahlzeit die Damen und die Herren da draußen!

Ich brauch für eine kleine Anwendung ein zwei Spalten Layout. In der linken Spalte die etwa 2/3 des Bildschirmes einnehmen soll, soll später eine Google-Maps-Karte eingebunden werden. Im rechten Bereich soll sich eine kleine Liste befinden.

Die Liste bekommt die Daten über eine XML Schnittstelle die über HTTP erreichbar ist. Die Daten habe ich nach zwei Tagen endlich zum anzeigen in die Liste bekommen aber jetzt scheitere ich an dem Layout der Anwendung. Ich verstehe noch nicht wirklich das Zusammenspiel der XML-Dateien, die relativen und absoluten Layouts und und und.

Was cool wäre, wenn mir jemand erklären könnte, wie meine main.xml auszusehen hat, damit ich das oben beschriebene erreichen kann.

Nebenbei muss ich noch erwähnen, dass Java nach wie vor immer noch Neuland für mich ist. Wo ich z.B. überhaupt noch nicht mit klar komme sind diese ominösen Spitzen Klammern an Datentypen, Klassen. Dann kommen zwischendurch noch Klammern wie () dazu und dann die ganzen Casts...

Quellcode anbei:

Code:
public class ApplicationMain extends ListActivity {
    
    private ArrayList<String> checkList = new ArrayList<String>();
    
    private static String getTagValue(final String sTag, final Element eElement){
        NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
        Node nValue = (Node) nlList.item(0); 
        return nValue.getNodeValue();    
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Override
    public void onCreate(Bundle savedInstanceState) {

        Context context = getApplicationContext();
        try {
            
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            
            DocumentBuilder builder = factory.newDocumentBuilder();
            
            Document doc = builder.parse("xxxxxxxxxxx");
            
            doc.getDocumentElement().normalize();
            
            NodeList nList = doc.getElementsByTagName("contact");

            for(int temp=0; temp < nList.getLength(); temp++) {

               Node nNode = nList.item(temp);

               if(nNode.getNodeType() == Node.ELEMENT_NODE) {

                  Element eElement = (Element)nNode;
                  
                  String id = getTagValue("id",eElement);
                  String pre = getTagValue("pre",eElement);
                  String last = getTagValue("last",eElement);
                  checkList.add(pre + " " + last);

                }
            }
            
            super.onCreate(savedInstanceState);
            
            setContentView(R.layout.main);
            
            ArrayAdapter adapter = new ArrayAdapter(context,R.layout.list_item,
                    checkList);
            
            setListAdapter(adapter);
            
            adapter.notifyDataSetChanged();
            
        } catch (Exception e) {
            CharSequence text = "XML Parsing Exception: " + e.getMessage();
            int duration = Toast.LENGTH_SHORT;
            Toast toast = Toast.makeText(context, text, duration);
            toast.show();
        }
    }

}
main.xml
HTML:
<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     >
     <ListView  
         android:id="@android:id/list"
         android:layout_width="fill_parent" 
         android:layout_height="wrap_content" 
         />
     <TextView android:id="@android:id/empty"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="Empty set"
         />
 </LinearLayout>
 
v Ralle v

v Ralle v

Stammgast
Hallo,

ich möchte dir nicht die Lösung geben, nur ein paar Tips.

Wenn du es wirklich ganz simpel haben willst, reicht dir ein Linearlayout aus. Da kannst du einfach die Orientation auf vertikal stellen und anschließend fügst du nur zwei Kinder ein. Bei den Kindern stellst du als layout_width "fill_parent" ein. Und jetzt kommt der coole Teil: dort kannst du ein Wert für "weight" angeben. Dieser liegt zwischen 0 und 1 und die Summe des Weights aller Kinder muss 1 ergeben. So kannst du ganz einfach dein 2/3 Verhältnis einstellen.

Wirklich professionell würde man dein Vorhaben aber mit Fragments umsetzen. Vielleicht hilft dir der Link da besser: Fragments | Android Developers

Was ich aber immer wieder klasse finde, wenn Leute von Java fast nichts verstehen und denken "jetzt programmiere ich mal ne App". So einfach ist das dann nun doch nicht ;) Du solltest dir vielleicht erstmal die Grundlagen ansehen und verstehen. Dafür gibt es genug Tutorials im Internet. Wenn du dich sogar wunderst, wenn auf einmal solche Klammern () hin müssen, dann hast du ja noch nicht mal die Syntax verinnerlicht. Das gibt mir zu denken übrig.

Und zum Abschluss. Die ominösen eckigen Klammern nennt man Generics ;)
 
S

Schranz0r_23

Neues Mitglied
Ah vielen vielen Dank. Die Fragments schau ich mir direkt morgen an, da ich hier Zuhause keine funktionierende IDE habe. Ich programmiere nämlich idr. nicht in Java. Also nicht falsch verstehen. Vom programmieren hab ich ne menge Ahnung, nur halt nicht von Java. Daher ist die Syntax auch sehr ungewohnt. Hab jetzt fast 8 Jahre nur Web Programmierung gemacht. Was ich auch sehr ungewohnt finde, dass man hier den Dereferenzierungsoperator nicht anwendet... egal egal, mit Deinen Sachen haste mir schon geholfen.

Edit:
Wenn wir schon mal dabei sind.. Wie kann ich diese Zeile lesen? Darum ging es mir nämlich, der Rest ist simples OOP.

private ArrayList<String> checkList = new ArrayList<String>();
 
v Ralle v

v Ralle v

Stammgast
Eine ArrayListe erkläre ich jetzt nicht. Das Konzept sollte klar sein. Zu den Generics: Die Liste muss wissen, was für Objekte sie beinhaltet. Das macht alles beim Programmieren einfach, zB. beim Iterieren über die Liste. Das Schlagwort ist hier auch Typsicherheit. Die Liste soll beispielsweise nicht ein String, Integer, etc. Objekt enthalten.

Du kannst den Aufruf also eine ArrayListe von Strings verstehen. Stell dir das mit den eckigen Klammern einfach so vor, dass die Klasse ArrayList konkretisiert wird.

Das new ArrayList<String>(); sieht anfangs vielleicht komisch aus, macht aber sehr viel Sinn. Einfach der Vergleich:

new ArrayList<String>();
new Object();

ArrayList wird halt nur konkretisiert, das halt Syntax die man so hinnehmen muss. Für den Rest bitte googlen ;)

Edit: schau auch mal bei der Insel vorbei http://openbook.galileocomputing.de...07_001.htm#mjc4a1f6f3499a02fb64fe89046739edca
 
Fr4gg0r

Fr4gg0r

App-Anbieter (Werbung)
v Ralle v schrieb:
Hallo,

ich möchte dir nicht die Lösung geben, nur ein paar Tips.

Wenn du es wirklich ganz simpel haben willst, reicht dir ein Linearlayout aus. Da kannst du einfach die Orientation auf vertikal stellen und anschließend fügst du nur zwei Kinder ein. Bei den Kindern stellst du als layout_width "fill_parent" ein. Und jetzt kommt der coole Teil: dort kannst du ein Wert für "weight" angeben. Dieser liegt zwischen 0 und 1 und die Summe des Weights aller Kinder muss 1 ergeben. So kannst du ganz einfach dein 2/3 Verhältnis einstellen.
Fragments sind doch für Tablets gedacht und was stört dich an der Lösung mit dem LinearLayout?
Als orientation meinst du wohl horizontal ;) welches der default wert ist.
 
v Ralle v

v Ralle v

Stammgast
Nichts stört mich daran, sonst hätte ich es ja nicht erklärt :) Jep, dann mein ich halt horinzontal ;) Ich komm da immer wieder durcheinander. Bedeutet horizontal nicht parallel zum Horizont?! Ich gehe immer von der Trennlinie der Kinder, dass die parallel, ist aber genau anders rum, daher verwechsle ich das immer :D Komische Denkblockade.
 
S

Schranz0r_23

Neues Mitglied
Moin!

Danke erstmal für die Hilfe hier.

Habe nun meine main.xml so wie ich das gerne hätte:
HTML:
<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     >
     <ListView  
         android:id="@+id/customer_list_view"
         android:layout_width="350px"
         android:layout_height="wrap_content"
         android:layout_weight="0"
         />
     <TextView android:id="@+id/customer_text_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="Kein Kunde gewählt"
         android:layout_weight="1"
         />
 </LinearLayout>
Die Fragments hätte ich gerne genutzt. Leider hat mein Eclipse gesagt, er könne die jeweiligen Basisklassen der Fragmente nicht finden. Liegt es eventuell daran, dass ich als Project Build Target Google APIs, P.:2.2, L:8 verwende? Ist auch halb so wild jetzt, da ja mein Layout so ausschaut wie ich das gerne hätte.

Nun bin ich allerdings an einer neuen Android Baustelle.. Wie schon erwähnt, hätte ich im ersten Step im linken Bereich des Layouts gerne eine Liste mit Kunden.

Dazu habe ich mir eine Klasse namens CustomerListView angelegt die von der Klasse ListActivity erbt. Jetzt verstehe ich nicht so recht, wie ich die Daten dieser ListActivity in meine Liste reinbekomme, die in der main.xml definiert wurde (customer_list_view). Also wo an welcher Stelle (Ich vermute mal in der MainActivity), muss ich dem Kollegen sagen, dass er die Daten aus der CustomerActivity in die customer_list_view schreibt.

Danke

CustomerListView
Code:
package com.packages;

import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;

import android.widget.ArrayAdapter;
import android.widget.Toast;

public class CustomerActivity extends ListActivity {
    
    private ArrayList<String> customerList = new ArrayList<String>();
    
    private static String getTagValue(final String sTag, final Element eElement){
        NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
        Node nValue = (Node) nlList.item(0); 
        return nValue.getNodeValue();    
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Context context = getApplicationContext();
        
        try {
            
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse("xxxxxxx");
            doc.getDocumentElement().normalize();
            
            NodeList nList = doc.getElementsByTagName("contact");

            for(int temp=0; temp < nList.getLength(); temp++) {
               Node nNode = nList.item(temp);
               if(nNode.getNodeType() == Node.ELEMENT_NODE) {
                  Element eElement = (Element)nNode;
                  String id = getTagValue("id",eElement);
                  String pre = getTagValue("pre",eElement);
                  String last = getTagValue("last",eElement);
                  customerList.add(pre + " " + last);
                }
            }
            
            setContentView(R.layout.main);
            
            ArrayAdapter adapter = new ArrayAdapter(context,
                                                    android.R.layout.simple_list_item_1,
                                                    customerList);
            setListAdapter(adapter);
            adapter.notifyDataSetChanged();
            
        } catch (Exception e) {
            CharSequence text = "XML Parsing Exception: " + e.getMessage();
            int duration = Toast.LENGTH_SHORT;
            Toast toast = Toast.makeText(context, text, duration);
            toast.show();
        }
    }

}
MainActivity
Code:
public class Main extends Activity {

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


        /*
        ProgressDialog dialog = ProgressDialog.show(Main.this,
                "", 
                "Loading. Please wait...",
                true);
        */
        try {
            
        } catch (Exception e) {
            CharSequence msg = "Fehler: " + e.getMessage();
            ToastMessage.create(msg, context);
        }
        
        
    }
    
}
Der Vollständigkeit halber, die ToastMessage-Klasse anbei:
Code:
public class ToastMessage {
    
    static public void create(CharSequence msg, Context context) {
        CharSequence text = msg;
        int duration = Toast.LENGTH_SHORT;
        Toast toast = Toast.makeText(context, text, duration);
        toast.show();
    }

}
 
Fr4gg0r

Fr4gg0r

App-Anbieter (Werbung)
mMn solltest du eine Klasse erstellen, die von Adapter oder ListView erbt statt von Activity. Du erstellst ja auch keine 3. Activity für das TextView. ;)

Wenn du von ListView erbst, müsstest du das xml entsprechend anpassen:
statt ListView
de.2spaltenlayout.MyListView
oder du erbst von Adapter (in deinem Fall ArayAdapter), baust da deine Liste auf, und kannst dann wie gehabt in der MainActivity
ListView lv = findViewById(R.id.customer_list_view);
lv.setAdapter(new MyArrayAdapter());
das anzeigen lassen.

Ansonsten könntest du auch alles was du in CustomerActiviy hast, auch in die MainActivity verlegen ;).
Je nachdem wie dus gern hättest.
 
S

Schranz0r_23

Neues Mitglied
Sorry, aber da komme ich noch nicht so ganz mit. Haste eventuell Links in Petto? Ich weis nämlich noch nicht so ganz ausm Kopf wie ich meine Klasse komplett anpassen muss, sobald ich von einer anderen Erbe. Wenn ich z.B. von extends ListActivity nach ListView wechsel, dann schaut der Konstruktur und die onCreate..Methode ja anders aus.

Danke
 
S

Schranz0r_23

Neues Mitglied
HA. Ich hab et mir ma einfach gemacht und Teile aus dem ContactManager aus der Doku einfach gemopst.

So find ich den Code schomma ganz gut:

Code:
package com.packages;

import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class Main extends Activity {

    public static final String TAG = "Kontakt Manager";

    private Button mAddAccountButton;
    private ListView mContactList;
    private boolean mShowInvisible;
    private CheckBox mShowInvisibleControl;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.contact_manager);
        
        Context context = getApplicationContext();
        
        /*
        ProgressDialog dialog = ProgressDialog.show(Main.this,
                "", 
                "Loading. Please wait...",
                true);
        */
        try {
            mContactList = (ListView) findViewById(R.id.contactList);
            
            // Initialize class properties
            //mShowInvisible = false;
            //mShowInvisibleControl.setChecked(mShowInvisible);
            
            // Register handler for UI elements
            //mAddAccountButton.setOnClickListener(new View.OnClickListener() {
            //    public void onClick(View v) {
            //    }
            //});
            
            //mShowInvisibleControl.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            //    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            //        mShowInvisible = isChecked;
            //        //populateContactList();
            //    }
            //});
            
            populateContactList();
            
        } catch (Exception e) {
            CharSequence msg = "Fehler: " + e.getMessage();
            ToastMessage.create(msg, context);
        }
    }
    
    private void populateContactList() {
        // Build adapter with contact entries
        Cursor cursor = getContacts();
        String[] fields = new String[] {
                ContactsContract.Data.DISPLAY_NAME
        };
        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.contact_entry, cursor,
                fields, new int[] {R.id.contactEntryText});
        mContactList.setAdapter(adapter);
    }
    
    private Cursor getContacts() {
        // Run query
        Uri uri = ContactsContract.Contacts.CONTENT_URI;
        String[] projection = new String[] {
                ContactsContract.Contacts._ID,
                ContactsContract.Contacts.DISPLAY_NAME
        };
        String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" +
                (mShowInvisible ? "0" : "1") + "'";
        String[] selectionArgs = null;
        String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";

        return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
    }
    
}
Nun muss ich allerdings die Methode getContacts modifizieren, dass dort nicht auf die interne Kontaktliste zurückgegriffen wird, sondern eben auf die XML-Struktur.

Dazu habe ich ja noch folgenden funktionierenden Code:
Code:
        Context context = getApplicationContext();
        
        try {
            
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse("http://xxxx");
            doc.getDocumentElement().normalize();
            
            NodeList nList = doc.getElementsByTagName("contact");

            for(int temp=0; temp < nList.getLength(); temp++) {
               Node nNode = nList.item(temp);
               if(nNode.getNodeType() == Node.ELEMENT_NODE) {
                  Element eElement = (Element)nNode;
                  String id = getTagValue("id",eElement);
                  String pre = getTagValue("pre",eElement);
                  String last = getTagValue("last",eElement);
                  customerList.add(pre + " " + last);
                }
            }
            
            setContentView(R.layout.main);
            
            ArrayAdapter adapter = new ArrayAdapter(context,
                                                    android.R.layout.simple_list_item_1,
                                                    customerList);
            setListAdapter(adapter);
            adapter.notifyDataSetChanged();
            
        } catch (Exception e) {
            CharSequence text = "XML Parsing Exception: " + e.getMessage();
            int duration = Toast.LENGTH_SHORT;
            Toast toast = Toast.makeText(context, text, duration);
            toast.show();
        }
Tja und jetzt weis ich auch nicht mehr weiter... Denn ich habe folgendes Verständnisproblem:

Die Daten aus dem XML-Doc speichere ich in einer ArrayList<String>.
private ArrayList<String> customerList = new ArrayList<String>();

Der ContactManager speichert die Kontakte allerdings so:
private ListView mContactList;

bzw. wird dort ein SimpleCursorAdapter injiziert
mContactList.setAdapter(adapter);

Ich muss es also irgendwie hinbekommen, dass ich eine Methode getXMLContacts habe, die mir die Daten so zurückliefert:

return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
 
Ähnliche Themen - Simples 2-Spalten-Layout: Wie geht das? Antworten Datum
1
4