Zugriff Layout in Fragmenten

  • Antworten:13
  • Bentwortet
Robbiani Renato
  • Forum-Beiträge: 609

10.06.2019, 21:58:57 via Website

Hallo zusammen

Ich habe mehrere Tabulatoren welche ich mit Fragmenten aufgebaut habe. Nun möchte ich die einzelnen Fragmente mit Daten füllen.
So wie ich es mache führt es zu einem "FATAL EXCEPTION". Darum gehe ich davon aus, dass es so nicht geht.

Also ich habe die einzelnen Fragment Darauf habe ich einzelne TextViews. Diese kann ich wie folgt initialisieren.

private TextView txt_aufgang;

und zuordnen

txt_aufgang = findViewById(R.id.txt_aufgang_wert);

Im onCreate

Wenn ich nun Daten hinein schreiben möchte führt dies zu einem Absturz.

txt_aufgang.setText("00:00");

Wie muss ich auf die TextViews zugreifen damit die Daten auch am richtigen Ort ankommen?

Gruss Renato

— geändert am 10.06.2019, 22:17:38 durch Moderator

Kommentieren
Beste Antwort
Jokel
  • Forum-Beiträge: 1.530

16.06.2019, 21:35:33 via Website

Du warst mit dem post schnellere als ich.

return inflater.inflate(R.layout.fragment_frag_sonne, container, false);

Wird nicht gehen denn du Inflatest das Layout zweimal.
Du musst deine View rootView zurückgeben.

return rootView;

Schaue dir den link von Pascal nochmal genau an.

— geändert am 16.06.2019, 21:40:10

Hilfreich?
Pascal P.
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

10.06.2019, 22:17:20 via Website

Hallo Renato,

das Vorgehen ist ansich richtig, aber im Fragment musst du in der onCreateView das passende Layout mit dem LayoutInflater erstellen und dann kannst du damit arbeiten:

https://alvinalexander.com/source-code/android/android-example-oncreateview-method-fragment-class

Du musst erst deine View "erstellen" und dann kannst du mit rootView.findViewById etc. weiterarbeiten.
In einer Activity wird dieser schritt bereits von setContentView erledigt, doch sowas gibts bei Fragments nicht.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 609

11.06.2019, 16:34:34 via Website

Ciao Pascal

Danke für die Antwort. Aber ich werde nicht so schalu damit.
Die Zeile

getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);

führt bei mir zu einem Absturz.
Auch wenn ich mit setText etwas versuche anzuzeigen erscheint nichts.

Gruss Renato

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

11.06.2019, 16:36:38 via App

Poste mal mindestens dein Fragment Code und wie du dieses aus der Activity lädst.
Zudem die genaue Fehlermeldung, sonst kann ich nur raten.

DisplayAsHomeUp solltest du evtl auch in der Activity machen. Wieso brauchst du das im Fragment?

— geändert am 11.06.2019, 16:37:44

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Jokel
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 609

11.06.2019, 17:42:08 via Website

Ciao Pascal

Die App hat im unteren Berich drei Tabulatoren mit drei Fragmenten:

image

Dort wo steht "das ist ein test" will ich mein Ergebniss hinschreiben. Die Berechnung nehme ich in der MainActivity vor. Die Resultate sollen dann auf den Verschiedenen Fragmenten stehen. Also müssen die Daten von der MainActivity auf die Fragmente kommen.

MainActivity:

package ch.robbisoft.sun_app;

import android.app.DatePickerDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static android.Manifest.permission.*;

public class Main extends AppCompatActivity
implements frag_sonne.OnFragmentInteractionListener,
frag_astro.OnFragmentInteractionListener,
frag_mond.OnFragmentInteractionListener{

public static final String APP = "SONNE";
String[] rechte = new String[]{
        ACCESS_NETWORK_STATE,
        ACCESS_COARSE_LOCATION,
        ACCESS_FINE_LOCATION
};

private Context ctx;
private String str_text;
public static final int MULTIPLE_PERMISSIONS = 99;
private EditText txt_lang;
private EditText txt_breit;
private EditText txt_hoch;
private EditText txt_datum;
private EditText txt_zone;
private TabLayout tabulator;
private Fragment fragment = null;
private Date datum;
private Calendar kalender;
private DatePickerDialog datumdialog;
private DatePickerDialog.OnDateSetListener listener;
private LocationManager posmanager;
private LocationListener horcher;

private TextView txt_sonne_auf;

private Double b_breite = (double) 0;
private Double b_laenge = (double) 0;

public Double getB_breite() {
    return b_breite;
}

public void setB_breite(Double b_breite) {
    this.b_breite = b_breite;
}

public Double getB_laenge() {
    return b_laenge;
}

public void setB_laenge(Double b_laenge) {
    this.b_laenge = b_laenge;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ctx = getApplicationContext();
    //Verhindert dass eine Tastatur angezeigt wird
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

    txt_lang = findViewById(R.id.edt_lang);
    txt_breit = findViewById(R.id.edt_breit);
    txt_hoch = findViewById(R.id.edt_hoch);
    txt_datum = findViewById(R.id.edt_datum);
    txt_zone = findViewById(R.id.edt_zone);

    //Tabulatoren aufbauen
    tabulator = (TabLayout) findViewById(R.id.tab_anzeige);
    TabLayout.Tab tab_sonne = tabulator.newTab();
    tab_sonne.setText(getResources().getString(R.string.lbl_sonne));

// tab_sonne.setIcon();
TabLayout.Tab tab_astro = tabulator.newTab();
tab_astro.setText(getResources().getString(R.string.lbl_astro));
// tab_astro.setIcon();
TabLayout.Tab tab_mond = tabulator.newTab();
tab_mond.setText(getResources().getString(R.string.lbl_mond));
// tab_mond.setIcon();
tabulator.addTab(tab_sonne, true);
tabulator.addTab(tab_astro);
tabulator.addTab(tab_mond);
//Den richtigen Tab öffnen
tabulator.addOnTabSelectedListener((new TabLayout.BaseOnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
//Selektieren der richtigen Seite
switch (tab.getPosition()){
case 0 : fragment = new frag_sonne();
break;
case 1 : fragment = new frag_astro();
break;
case 2 : fragment = new frag_mond();
break;
}
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.simpleFrameLayout, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    }));
    //erste seite anzeigen
    fragment = new frag_sonne();
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.replace(R.id.simpleFrameLayout, fragment);
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    ft.commit();
    //Aktuelles Datum anzeigen
    SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
    kalender = Calendar.getInstance();
    datum = kalender.getTime();
    String str_datum = sdf.format(datum);
    txt_datum.setText(str_datum);
    //Beim anklicken Datumsdialog anzeigen
    listener = new DatePickerDialog.OnDateSetListener() {
        @Override
        public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
            //gewähltes Datum setzen
            SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
            kalender.set(year, month, dayOfMonth);
            Date datum = kalender.getTime();
            String str_datum = sdf.format(datum);
            txt_datum.setText(str_datum);
        }
    };
    txt_datum.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int n_jahr, n_monat , n_tag;
            n_jahr = kalender.get(Calendar.YEAR);
            n_monat = kalender.get(Calendar.MONTH);
            n_tag = kalender.get(Calendar.DAY_OF_MONTH);
            v.setFocusable(false);

            datumdialog = new DatePickerDialog(Main.this, listener, n_jahr, n_monat, n_tag);
            datumdialog.show();
        }
    });

    //prüft ob OS Version > 6 ist, denn vorher kann nicht geprüft werden
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        //prüfen ob Rechte vorhanden sind um auf die GPS Daten zu zugreifen
        if (pruefrechte()) {
            str_text = getResources().getString(R.string.lbl_start_neu);
            Toast.makeText(ctx, str_text, Toast.LENGTH_SHORT).show();
            initial();

        } else {
        }
    }else{
        str_text = getResources().getString(R.string.lbl_start_alt);
        Toast.makeText(ctx, str_text, Toast.LENGTH_SHORT).show();
        initial();
    }
}

/**********************************************************************************************
* Ermittelt die Posiotn
*
* @author robbisoft @since 2. Juni 2019
* @param
* @return
**********************************************************************************************/
private void position(){
    posmanager = (LocationManager) getSystemService(LOCATION_SERVICE);
    horcher = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            Double lang = location.getLongitude();
            Double breit = location.getLatitude();
            Double hoch = (double) 0;
            if( location.hasAltitude() )
                hoch = location.getAltitude();

            setB_breite( breit );
            setB_laenge( lang );

            txt_lang.setText(lang.toString());
            txt_breit.setText(breit.toString());
            txt_hoch.setText(hoch.toString());
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };
    //ungenau möchte noch mit den Optionen verbinden

// posmanager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, (LocationListener) ctx);
//genau
posmanager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, (LocationListener) horcher);
}

/**********************************************************************************************
* Ermittelt die Position, berechnet die Daten und stellt die ergebnisse dar
*
* @author robbisoft @since 2. Juni 2019
* @param
* @return
**********************************************************************************************/
private void initial(){
    //Gespeicherte Position lesen damit sofort was angezeigt wird
    lese_daten();
    Double b_breit = getB_breite();
    Double b_lang = getB_laenge();
    txt_breit.setText(b_breit.toString());
    txt_lang.setText(b_lang.toString());
    //Position ermitteln
    position();
    //Daten Berechnen und Werte Anzeigen
    rechne(b_breit, b_lang, datum);
}

/**********************************************************************************************
* Prüft die Rechte der App
*
* @author robbisoft @since 7. Juni 2019
* @param
* @return
**********************************************************************************************/
private boolean pruefrechte(){
    int result;
    List listPermissionsNeeded = new ArrayList<>();
    for (String p:rechte)
    {
        result = ContextCompat.checkSelfPermission(this,p);
        if (result != PackageManager.PERMISSION_GRANTED)
        {
            listPermissionsNeeded.add(p);
        }
    }
    if (!listPermissionsNeeded.isEmpty())
    {
        ActivityCompat.requestPermissions(this, (String[]) listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),MULTIPLE_PERMISSIONS );
        // keine permissions gesetzt
        return false;
    }
    // alle permissions gesetzt
    return true;
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode)
    {
        case MULTIPLE_PERMISSIONS:
        {
            if (grantResults.length > 0)
            {
                String permissionsDenied = "";
                for (String per : permissions)
                {
                    if(grantResults[0] == PackageManager.PERMISSION_DENIED)
                    {
                        permissionsDenied += "\n" + per;
                    }
                }
                // Nach dem ersten Male
            }
            return;
        }
    }
}

@Override
public void onFragmentInteraction(Uri uri) {

}

@Override
public void onPointerCaptureChanged(boolean hasCapture) {

}

@Override
protected void onDestroy() {
    super.onDestroy();

    double breit, lang;
    breit = getB_breite();
    lang = getB_laenge();
    schreibe_daten(breit, lang);
}

/**********************************************************************************************
* Liest die Daten aus dem Speicher
*
* @author robbisoft @since 8. Juni 2019
* @param
* @return
**********************************************************************************************/
private void lese_daten(){
    float breit, lang;
    SharedPreferences pref = getSharedPreferences(APP, 0);
    breit = pref.getFloat("BREIT", 0);
    setB_breite((double) breit);
    lang = pref.getFloat("LANG", 0);
    setB_laenge((double) lang);
}

/**********************************************************************************************
* Schreibt die Daten in den Speicher
*
* @author robbisoft @since 8. Juni 2019
* @param 'Länge und Breite der aktuellen Position
* @return
**********************************************************************************************/
private void schreibe_daten(double breit, double lang){
    SharedPreferences pref = getSharedPreferences(APP, 0);
    SharedPreferences.Editor edit = pref.edit();
    edit.putFloat("BREIT", (float) breit);
    edit.putFloat("LANG", (float) lang);
    edit.commit();
}

/**********************************************************************************************
*
*
* @author robbisoft  @since 11. Juni 2019
* @param 'Breitengrad der Position
* @param 'Längengrad der Position
* @param 'Datum zum Berechnen
* @return
* @exception
* @throws
**********************************************************************************************/
private void rechne(Double breit, Double lang, Date datum){
    int zone = 0;

    try {
        Sun_calculator sun = new Sun_calculator();
        zone = sun.zeitzone(lang);
        sun.berechne(breit, lang, datum, zone);
        txt_zone.setText(Integer.toString(zone));
    } catch (ParseException e) {
        e.printStackTrace();
    }
}

}

Fragment Sonne;

package ch.robbisoft.sun_app;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link frag_sonne.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link frag_sonne#newInstance} factory method to
* create an instance of this fragment.
*/
public class frag_sonne extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";

private TextView txt_sonne_auf;

// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;

private OnFragmentInteractionListener mListener;

public frag_sonne() {
    // Required empty public constructor
}

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 *
 * @param param1 Parameter 1.
 * @param param2 Parameter 2.
 * @return A new instance of fragment frag_sonne.
 */
// TODO: Rename and change types and number of parameters
public static frag_sonne newInstance(String param1, String param2) {
    frag_sonne fragment = new frag_sonne();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_frag_sonne, container, false);

    txt_sonne_auf = rootView.findViewById(R.id.txt_aufgang_wert);
    txt_sonne_auf.setText("00:00");

    return inflater.inflate(R.layout.fragment_frag_sonne, container, false);
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) {
        mListener = (OnFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

/**
 * This interface must be implemented by activities that contain this
 * fragment to allow an interaction in this fragment to be communicated
 * to the activity and potentially other fragments contained in that
 * activity.
 * <p>
 * See the Android Training lesson <a href=
 * "http://developer.android.com/training/basics/fragments/communicating.html"
 * >Communicating with Other Fragments</a> for more information.
 */
public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}

}

In zeile 72 versuche ich den Text zu schreiben. Geht aber nicht.
Bin mir nicht ganz sicher, ob ich nicht in der MainActivity in Zeile 121 was machen kann.
Ich hoffe, dass du verstehst was ich machen will.

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

11.06.2019, 18:05:36 via Website

Hallo
Wie Pascal schon richtig sagte gehört die Actionbar in die MainActivity und nicht in die Fragment Cass.

Aber
getActivity() ist seit API 28 Deprecated wenn du dein Target auf API 28 hast wie es bei einen Standart Projekt ist geht das nicht mehr.

Als erstens schaue dir den Livecycle ders Fragment an.
Da werden eigentlich drei start Methoden benutzt.
onCreate , onCreateView, onActivityCreate
Die onCreate ist da nicht mehr so wichtig wie bei einer Activity.
In der onCreateView wird deine layout gesetzt und hier müsstest du auch hier deine FindviewByID machen. Denn in einem Fragment brachst du dafür den Kontext der unebenen View oder den der Activity.
Die View hast du ja in der Methode erstellt und wird ja am ende zurück gegeben.

Die die variablen dazu sollten im Klassenrumpf Definiert werden .
Damit sie später in der onActivityCreate was du als deine neue onCreate ansehen kannst zu Verfügung stehen.

Den Kontext der activity kannst du dir auch aus der onAttach( ) Methode holen.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

11.06.2019, 18:08:07 via Website

du warst schneller habe den code noch nicht gelesen.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

11.06.2019, 18:13:08 via Website

Zeile 72 leider gibt es hier keine zeilen Nummern.

edit

ok habe die Zeile gefunden du meisnst das.
txt_sonne_auf.setText("00:00");

Frage von wo aus, aus welchen listner willst du darauf zugreifen?
möchte jetzt nicht deinen ganzen Code durchgehen.

In übrigen wäre es wohl auch sinnvoller die Berechnungs- Methode in der Activity nicht Private zu machen sondern Public damit du sie auch aus der Fragment Klasse aufrufen kannst.

Auch wenn ich mit setText etwas versuche anzuzeigen erscheint nichts.

Wie ich schon sagte mache das setzen des Textes in der onActivityView. Dafür solte die variable eine Klassen variable sein.

Also das findviewbyid in der oncreateView und setzen in der onActivityView.
Oder aus einem listner heraus.

— geändert am 11.06.2019, 21:11:08

Hilfreich?
Pascal P.
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 609

16.06.2019, 20:30:49 via Website

Ciao Jokel

Stichwort Listner? Meinst du ich soll einen Händler für den Datenaustausch einrichten.

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

16.06.2019, 21:04:47 via Website

Nein das meinte ich nicht. Ich wollte wissen von wo aus du das setzen veranlassen willst.

Poste den Code mal so das man die zeilennummern auch Lesen kann vielleicht in einer Datei.

Glaube du verstehst nicht was ich gesagt habe. Und was ich meinte.

— geändert am 16.06.2019, 21:12:00

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 609

16.06.2019, 21:17:35 via Website

Hallo zusammen

Mein Problem ist, dass folgenden Code einfach nichts anzeigt ob wohl er läuft!

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_frag_sonne, container, false);

    txt_sonne_auf = rootView.findViewById(R.id.txt_aufgang_wert);
    txt_sonne_auf.setText("00:00");

    return inflater.inflate(R.layout.fragment_frag_sonne, container, false);
}

Wo muss ich die Daten ausgeben?

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

16.06.2019, 21:26:05 via Website

Hast du dir mal den livecycle von Fragment angesehen? Damit du verstehst welche Methoden beim Aufbau des Fragment der Reihe nach durchlaufen werden. Deine attach zb wird durchlaufen zu einem Zeitpunkt wo dein layout noch gar nicht geladen wurde.

In deinem gesamtem Code kann nur die eine Zeile sehen wo du auf die view zugreift.

Und wie ich schon sagte mache das erst In der onActivityview denn da ist dein layout geladen.

Hilfreich?
Kommentieren
Beste Antwort
Jokel
  • Forum-Beiträge: 1.530

16.06.2019, 21:35:33 via Website

Du warst mit dem post schnellere als ich.

return inflater.inflate(R.layout.fragment_frag_sonne, container, false);

Wird nicht gehen denn du Inflatest das Layout zweimal.
Du musst deine View rootView zurückgeben.

return rootView;

Schaue dir den link von Pascal nochmal genau an.

— geändert am 16.06.2019, 21:40:10

Hilfreich?
Pascal P.
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 609

16.06.2019, 21:50:12 via Website

Ciao Jokel

Haha! Nun wird auch was angezeigt. Super danke.

Ich habe gesehen, dass man den Fragmenten Argumente übergeben kann. Vielleicht kann ich so die gewünschten Daten rüberbringen. Ich schaue mal ob ich das hinkriege.

Gruss Renato

Hilfreich?
Kommentieren