Smarthome App #7: Raumsteuerung (1/2)


29.11.2016  |  Tutorial, Smarthome App

Im letzten Tutorial wurde der Einstellungs-Bildschirm der Smarthome App implementiert. In diesem Beitrag wird damit angefangen, die Raumsteuerung zu erstellen.

Dieses Tutorial als Video

Als erstes wird ein Layout angelegt, das angezeigt wird, wenn eine Liste keine Elemente enthält. Dazu klickst du den Ordner mobile -> res -> layout oder eine Datei darin mit der rechten Maustaste an und wählst "New -> Layout resource file". Hier gibst du als Namen "empty_item" und als "Root element" "RelativeLayout" ein und klickst auf "OK". In der Datei, die sich nun geöffnet hat, klickst du in der Leiste unten auf "Text", um zur Textansicht zu wechseln und ersetzt dort den gesamten Code mit diesem:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:padding="5dp">

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardElevation="@dimen/cardViewElevation"
        android:layout_margin="5dp"
        app:cardUseCompatPadding="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="10dp">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <ImageView
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_margin="5dp"
                    android:id="@+id/empty_icon"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAppearance="?android:attr/textAppearanceLarge"
                    android:textColor="@color/textColorDark"
                    android:layout_gravity="center_vertical"
                    android:id="@+id/empty_title"/>

            </LinearLayout>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="@color/textColorDark"
                android:id="@+id/empty_info"/>

        </LinearLayout>

    </android.support.v7.widget.CardView>

</RelativeLayout>

RoomFragment designen

Danach öffnest du die Datei mobile -> res -> layout -> fragment_room.xml und fügst im oberen FrameLayout-Tag diese Zeilen hinzu:
android:background="@color/layoutBackground"
android:id="@+id/frame"
Anschließend schreibst du diesen Code zwischen den öffnenden und den schließenden FrameLayout-Tag:
<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/room_list"></android.support.v7.widget.RecyclerView>

<include
    layout="@layout/loading_animation"
    android:visibility="gone"
    android:id="@+id/loading_animation" />

<include
    layout="@layout/empty_item"
    android:visibility="gone"
    android:id="@+id/empty_item" />

RoomFragment implementieren

Um mit der Implementierung der Raumsteuerung zu beginnen, wird die Datei mobile -> java -> de.smarthome_blogger.smarthome -> RoomFragment.java geöffnet. Hier erstellst du nun über der Methode "public RoomFragment()" ein paar neue Variablen:
String location, title;

boolean setState = false;

//RecyclerView
RecyclerView.Adapter roomAdapter;
GridLayoutManager glm;
ArrayList<RoomItem> roomItems;
RecyclerView roomArray;

View roomView;
Als nächstes wird innerhalb der Klasse RoomFragment eine neue Klasse angelegt, indem du am unteren Ende von RoomFragment aber über der letzten schließenden Klammer den folgenden Code hineinschreibst:
public class RoomItem{
    private String name, device, icon, type, value;

    public RoomItem(String name, String device, String icon, String type, String value){
        this.name = name;
        this.device = device;
        this.icon = icon;
        this.type = type;
        this.value = value;
    }

    /**
     * Gibt den Namen des Items zur&uuml;ck
     * @return
     */
    public String getName(){
        return name;
    }

    /**
     * Gibt den Wert des Items zur&uuml;ck
     * @return
     */
    public String getValue(){
        return value;
    }

    /**
     * Gibt den Typ des Items zur&uuml;ck
     * @return
     */
    public String getType(){
        return type;
    }

    /**
     * Gibt den Icon des Items zur&uuml;ck
     * @return
     */
    public String getIcon(){
        return icon;
    }

    /**
     * Gibt das Device des Items zur&uuml;ck
     * @return
     */
    public String getDevice(){
        return device;
    }
}
Wenn die Klasse fertig hinzugefügt wurde, wird weiter oben die Methode "public View onCreateView()" bearbeitet. Dabei werden die Zeilen
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_room, container, false);
mit folgendem Code ersetzt:
// Inflate the layout for this fragment
roomView = inflater.inflate(R.layout.fragment_room, container, false);

Bundle bundle = getArguments();
location = bundle.getString(MainActivity.EXTRA_LOCATION);
title = bundle.getString(MainActivity.EXTRA_TITLE);

roomArray = (RecyclerView) roomView.findViewById(R.id.room_list);
roomArray.setHasFixedSize(true);
glm = new GridLayoutManager(getContext(), getResources().getInteger(R.integer.grid_columns));
glm.setOrientation(GridLayoutManager.VERTICAL);
roomArray.setLayoutManager(glm);

roomItems = new ArrayList<>();

loadRoomData();

return roomView;
Dieser Code initialisiert die Variablen, die du vorher erstellt hast.

Fehlermeldungen ausgeben

Damit übergebene Fehlermeldungen auf dem Bildschirm ausgegeben werden können, wird die Methode "public void fehlermeldung()" angelegt, die als Parameter einen Text enthält, der dann ausgegeben wird. Um die Methode zu erstellen, schreibst du folgenden Code in die Klasse RoomFragment:
/**
 * Zeigt die &uuml;bergebene Fehlermeldung an
 * @param msg
 */
public void fehlermeldung(String msg){
    Snackbar.make(roomView.findViewById(R.id.frame), msg, Snackbar.LENGTH_SHORT).show();
}

Raumdaten laden

Da in der Methode "public void onCreateView()" die Funktion "loadRoomData()" aufgerufen wird, sie aber noch nicht existiert, wird sie nun implementiert. Schreibe dazu den folgenden Code in die Klasse:
/**
 * L&auml;dt die Raum-Daten vom Server und zeigt sie an
 */
public void loadRoomData(){
    roomView.findViewById(R.id.loading_animation).setVisibility(View.VISIBLE);

    final Map<String, String> requestData = new HashMap<>();
    requestData.put("action", "getroomdata");
    requestData.put("username", SaveData.getUsername(getContext()));
    requestData.put("password", SaveData.getPassword(getContext()));
    requestData.put("room", location);

    HTTPRequest.sendRequest(getContext(), requestData, SaveData.getServerIp(getContext()), new HTTPRequest.HTTPRequestCallback() {
        @Override
        public void onRequestResult(String result) {
            roomView.findViewById(R.id.loading_animation).setVisibility(View.GONE);

            //Ergebnis in Log schreiben
            Log.i("GetRoomData-Result", result);

            if(result.equals("wrongdata")){
                fehlermeldung("Anmeldung nicht m&ouml;glich!\nBitte logge dich erneut ein.");
            }
            else if(result.equals("unknownuser")){
                fehlermeldung("Dieser Benutzer existiert nicht.\nBitte logge dich erneut ein.");
            }
            else{
                try{
                    JSONObject jsonObj = null;
                    try{
                        jsonObj = new JSONObject(result);
                    }
                    catch(JSONException e){
                        e.printStackTrace();
                    }

                    JSONArray roomData = jsonObj.getJSONArray("roomdata");

                    for(int i = 0; i < roomData.length(); i++){
                        JSONObject c = roomData.getJSONObject(i);

                        roomItems.add(new RoomItem(c.getString("name"), c.getString("device"), c.getString("icon"),
                                c.getString("type"), c.getString("value")));
                    }

                    //Adapter setzen
                    roomAdapter = new RoomAdapter();
                    roomArray.setAdapter(roomAdapter);
                    roomAdapter.notifyDataSetChanged();
                }
                catch(Exception e){
                    fehlermeldung("Fehler beim Laden der Raumdaten");
                }

                if(roomItems.isEmpty()){
                    roomArray.setVisibility(View.GONE);

                    roomView.findViewById(R.id.empty_item).setVisibility(View.VISIBLE);
                    ((ImageView) roomView.findViewById(R.id.empty_icon)).setImageResource(Icons.getDrawerIcon(location));
                    ((TextView) roomView.findViewById(R.id.empty_title)).setText("Raum leer");
                    ((TextView) roomView.findViewById(R.id.empty_info)).setText("Diesem Raum wurden noch keine Ger&auml;te zugewiesen.");
                }
            }
        }

        @Override
        public void onError(String msg) {
            roomView.findViewById(R.id.loading_animation).setVisibility(View.GONE);
            fehlermeldung(msg);
        }
    });

}
Im nächsten Teil dieses Tutorials wird die Raumsteuerung fertiggestellt. Wenn du Fragen oder Probleme hast, hinterlasse mir gerne einen Kommentar.

Über den Autor


Sascha Huber

Hallo, ich bin Sascha, der Gründer von Smarthome Blogger.

Mit einer Leidenschaft für Technologie und einem Hintergrund als Software Engineer habe ich 2016 Smarthome Blogger gegründet. Mein Ziel war es schon immer, innovative Lösungen zu entdecken, die unser Leben einfacher und intelligenter gestalten können. In meinem beruflichen Leben arbeite ich täglich mit Software und Technik, aber auch in meiner Freizeit bin ich stets auf der Suche nach neuen technischen Spielereien und Möglichkeiten, mein Zuhause zu automatisieren und zu verbessern.

Auf Smarthome Blogger teile ich mein Wissen, meine Erfahrungen und meine Begeisterung für alles rund um das Thema Smarthome.



Dieser Beitrag hat dir gefallen?

Dann abonniere doch unseren Newsletter!