JavascriptProva

sabato 29 settembre 2018

Esercizio sul fragment: creazione e comunicazione con l'activity principale.

Ora voglio tenermi in esercizio con i Fragment.
Non riesco ancora a usare questo blog nella maniera che mi ero preposto, ossia come un diario per esercizi.
Programmiamo un esercizio al giorno sui Fragments, per 5 giorni. Potrebbe essere sufficiente.
Ecco, adesso rompo il mio esercizio e lo ricostruisco da capo.
Aggiunta di due fragment con messa a video in un Toast da parte della finestra principale del testo di una TextBox contenuta in uno di questi due fragments.

Ho cliccato col destro sul nome del package nella finestra "Progetto", e quindi ho cliccato New.
Nel menu ho cliccato Fragment -> Fragment (Blank), quindi ho eliminato le spunte, nella finestra, su include fragment factory methods e su include interface callback?.
, ho scelto un nuovo nome al posto di BlankFragment e Android Studio mi crea il fragment, ossia un file xml e un file java.

Sono stato messo un po' in crisi dal fatto che mi è stato messo tutto in un FrameLayout.
Nell'esercizio che ho fatto ieri non mi ero accorto di questo fatto, confuso da diversi tutorial.
Bene: all'interno del FrameLayout ci mettiamo un layout a nostro piacimento, Linear, Relative o altro.

Questo è l'XML di un fragment:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    tools:context=".fragment_origine">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:weightSum="10"
        tools:context=".fragment_origine">

        <!-- TODO: Update blank fragment layout -->

        <TextView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="@string/hello_blank_fragment" />

        <Button
            android:id="@+id/button4"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="Button" />

    </LinearLayout>

</FrameLayout> 
Per l'altro fragment faccio la stessa cosa, senza alcuna view particolare, ma solo con uno sfondo azzurrino:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragment_altro">

    <LinearLayout
        android:background="#AACCFF"
        android:layout_width="match_parent"
        android:layout_height="match_parent">


    </LinearLayout>



</FrameLayout> 

Ora che ho preparato i fragments, li dispongo all'interno del mainLayout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:id="@+id/container"
    tools:context=".MainActivity">
    
    <fragment
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/fragment1"
        android:name="com.example.antonello.studiofragment.fragment_origine"/>
    
    <fragment
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/fragment2"
        android:name="com.example.antonello.studiofragment.fragment_altro"/>
        



</LinearLayout> 
Funziona!


Ora devo recepire l'azione sul pulsante del primo fragment.
public class fragment_origine extends Fragment {
    TextView testo;
    Button button;
    public fragment_origine() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_origine, container, false);
        testo=view.findViewById(R.id.textview);
        button=view.findViewById(R.id.button4);
        
        return view;
    }
.....
Dichiaro e inizializzo le variabili di tipo TextView e Button.
Avevo dimenticato di specificare l'id per la TextView, e rimedio subito:
        <TextView
            android:id="@+id/textview"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="@string/hello_blank_fragment" />
Poi ho creato un'interfaccia:
    public interface OnTextReadListener{
        public void onTextRead(String messaggio);
    }
e ho dichiarato una variabile del tipo dell'interfaccia:
public class fragment_origine extends Fragment {
    OnTextReadListener mListener;
    TextView testo;
    Button button;
    public fragment_origine() {
        // Required empty public constructor
    }
.....
Ora devo fare in modo che all'evento onAttach(Context context) venga eguagliata alla variabile del tipo dell'interfaccia, mListener, la main activity alla quale il fragment si è "attaccato":
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mListener=(OnTextReadListener)context;
    }
Quindi vado a MainActivity e dichiaro che implementa l'interfaccia di cui sopra:
public class MainActivity extends AppCompatActivity implements fragment_origine.OnTextReadListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
Quindi scrivo, sempre in MainActivity, il codice del metodo da implementare:
    @Override
    public void onTextRead(String messaggio) {
        Toast.makeText(this,messaggio,Toast.LENGTH_LONG).show();
    }
Avviando il programma, non ottengo errori.
Ma finora ho solo creato una classe che implementa il metodo dell'interfaccia dichiarata nel fragment, non ho ancora subordinato l'esecuzione di questo metodo da parte del Button.
Provvedo:
        button.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View view) {
                mListener.onTextRead(testo.getText().toString());
            }
        });
E adesso funziona!