5

Ho un frammento con un metodo setName() che modifica un testo EditText, tramite la funzione setText.Accesso a un metodo di un frammento dall'attività ViewPager

Qual è il modo migliore per chiamare tale metodo dall'attività che ospita quel frammento per mezzo di un ViewPager?

In altre parole, come posso accedere ai metodi di Fragment (che modificano il layout di un frammento, ad esempio) dall'attività che ospita tale frammento per mezzo di un ViewPager?

Lo chiedo perché ho provato diversi modi, ma sempre con errori.

+0

Si può cercare di creare una variabile del frammento istanza con il 's metodo etName() nella tua classe di attività. Assegna la variabile al frammento quando lo installi. puoi quindi chiamare 'fragment.setName()' dalla tua attività – Scott

+0

Ho questo problema, ma chiamare fragment.setName() tramite un riferimento memorizzato ad esso, non è un problema. Il problema è che dal frammento, getActivity() restituisce null in modo che non sia possibile accedere alle viste. Tuttavia, posso accedere alle viste dall'attività e il frammento COULD inserisce informazioni nelle viste che appartengono al frammento alla configurazione. Ma in seguito, getActivity() restituisce null e potrebbe essere qualcosa con viewPager che prende il controllo del contesto in modo che getActivity non sia effettivamente valido? Quindi sarebbe necessario richiedere la vista dal Viewpager? Sto chiedendo. – carl

risposta

3

È possibile accedere ai metodi pubblici all'interno dei frammenti detenuti dal proprio ViewPager. È necessario (1) memorizzare un riferimento allo Fragment quando lo si crea e aggiungerlo all'elenco che sostituirà l'adattatore del cercapersone o (2) è necessario ottenere un riferimento al frammento dall'adattatore del cercapersone stesso. Per esempio:

Fragment fragmentA = null; //instance variable 

fragmenA = new Fragment(); //whereever you instantiate your fragment 

Se il metodo è

public void setName(String args){ 
    //do something 
} 

tutto quello che vi fare è chiamare tale metodo dal riferimento al frammento detenuta dalla tua ViewPager

fragmentA.setName(args); 

Si passa qualsiasi argomenti hai bisogno di chiamare un metodo normale. Nota questo funziona SOLO se stai chiamando un metodo all'interno di un frammento dal suo contenente ViewPager o FragmentActivity. Se vuoi fare il contrario, frammentare in attività, devi usare un inerface.

+0

Sì, lo so già. Ma cosa succede se sto cercando di istanziarlo usando qualcosa come Frag1 fragment = (Frag1) mAppSectionsAdapter.getItem (0) ;? Come dovrei usare il metodo quindi senza l'eccezione del puntatore nullo? – JZweige

+0

È come framment.getView() è sempre nullo! – JZweige

+0

Vuoi ottenere il riferimento dall'adattatore? Non sono al mio computer ma posso postare il codice più tardi se questo è il problema. – Rarw

8

So che è un po 'in ritardo, ma mi sono imbattuto nello stesso problema e forse aiuterà gli altri se già lo risolvi.

Il primo problema che ho riscontrato con ViewPager è che è quasi impossibile ottenere un riferimento a un frammento. I frammenti vengono creati dinamicamente in getItem() e quindi non è possibile impostare un ID e questi vengono automaticamente re-taged dalla swicher, quindi non è possibile trovarli per tag. Ci sono alcuni modi per farlo, ma sono tutti soluzioni alternative. (Update data in ListFragment as part of ViewPager)

Il modo in cui l'ho risolto era essenzialmente un doppio callback. Il frammento A ha un'interfaccia implementata dall'attività principale, l'attività principale ha un'interfaccia implementata dal frammento B. Ad es. un pulsante clink in Fragment A viene chiamata la funzione di callback in Main Activity, che a sua volta chiama il callback in Fragment B. Guarda il codice qui sotto. Spero di aver postato tutto e sarà d'aiuto. btw, ho provato solo questo con un ViewPager, ma presumo che funzionerebbe con qualsiasi tipo di comunicazione Fragment.

principale Avtivity java:

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentPagerAdapter; 
import android.support.v4.view.ViewPager; 

public class MainActivity extends FragmentActivity implements FragmentA.Caller { 

    SectionsPagerAdapter mSectionsPagerAdapter; 
    ViewPager mViewPager; 
    PassCallToB passOnToB = null; 
    FragmentManager myManager = null; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); 
     mViewPager = (ViewPager) findViewById(R.id.pager); 
     mViewPager.setAdapter(mSectionsPagerAdapter); 
    } 

    public class SectionsPagerAdapter extends FragmentPagerAdapter { 

     public SectionsPagerAdapter(FragmentManager fm) { 
      super(fm); 
      MyManager = fm; 
     } 

     @Override 
     public Fragment getItem(int position) { 
      Fragment fragment = null; 
      if(position == 0) { 
       fragment = new FragmentA(); 
      } else if (position == 1) { 
       fragment = new FragmentB(); 
       passOnToB = (PassCallToB)fragment; 
      } 
      return fragment; 
     } 

     @Override 
     public int getCount() { 
      return 2; 
     } 

     @Override 
     public CharSequence getPageTitle(int position) { 
      switch (position) { 
      case 0: 
       return "Frag A"; 
      case 1: 
       return "Frag B"; 
      } 
      return null; 
     } 

     public void setCallback() { 
      List<Fragment> frags = myManager.getFragments(); 
      for(Fragment fragment : frags) { 
       if(fragment instanceof FragmentB){ 
        passOnToB = (PassCallToB)fragment; 
       } 
      } 
     } 
    } 

    public interface PassCallToB { 
     public void passItOn(); 
    } 

    @Override 
    public void CallB() { 
     if(passOnToB instanceof Fragment) 
      passOnToB.passItOn(); 
     else { 
      mSectionsPagerAdapter.setCallback(); 
      passOnToB.passItOn(); 
     } 
    } 
} 

attività principale xml:

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/pager" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".MainActivity" > 

    <android.support.v4.view.PagerTitleStrip 
     android:id="@+id/pager_title_strip" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_gravity="top" 
     android:background="#33b5e5" 
     android:paddingBottom="4dp" 
     android:paddingTop="4dp" 
     android:textColor="#fff" /> 

</android.support.v4.view.ViewPager> 

Frammento A java:

import android.app.Activity; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentActivity; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewGroup; 
import android.widget.Button; 

public class FragmentA extends Fragment { 

    Button btnCallB = null; 

    Caller listener = null; 

    public FragmentA() { 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle inState) { 
     View rootView = inflater.inflate(R.layout.fragment_a, container, false); 

     btnCallB = (Button)rootView.findViewById(R.id.btnCallB); 
     btnCallB.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View view) { 
       listener.CallB(); 
      } 

     }); 

     return rootView; 
    } 

    public interface Caller { 
     public void CallB(); 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     if (activity instanceof FragmentActivity) { 
      listener = (Caller) activity; 
     } else { 
      throw new ClassCastException(activity.toString() + " must implemenet listener"); 
     } 
    } 

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

Frammento A xml:

<RelativeLayout 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" > 


    <TextView 
     android:id="@+id/textView1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentTop="true" 
     android:text="This is Fragment A" /> 

    <Button 
     android:id="@+id/btnCallB" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_below="@+id/textView1" 
     android:text="Call Fragment B" /> 

</RelativeLayout> 

frammento B Java:

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.Toast; 

public class FragmentB extends Fragment implements MainActivity.PassCallToB { 

    public FragmentB() { 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle inState) { 
     View rootView = inflater.inflate(R.layout.fragment_b, container, false); 
     return rootView; 
    } 

    @Override 
    public void passItOn() { 
     Toast.makeText(getActivity(), "Hello from B", Toast.LENGTH_SHORT).show(); 

    } 
} 

frammento B xml:

<RelativeLayout 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" > 

    <TextView 
     android:id="@+id/textView1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentTop="true" 
     android:text="This is Fragment B" /> 

</RelativeLayout> 
+0

Questo non funziona quando si ruota. Perché quando si ruota l'attività e vengono ricreati frammenti che ricreano anche il tuo SectionsPagerAdapter ma non chiama mai getItem (Android ricrea i frammenti senza chiamare getItem) che significa che passOnToB rimane nullo. – rve

+0

Ho modificato il mio codice in modo che funzioni dopo la rotazione dello schermo. Il trucco è impostare la funzione di callback non solo in getItem(), ma anche includere un metodo personalizzato nell'adattatore del cercapersone che cercherà attraverso i frammenti e imposterà manualmente la callback, quando viene trovato il frammento corretto. Ora è sufficiente controllare se la richiamata è impostata e impostarla se non nel metodo passOn. Spero che questo sia abbastanza chiaro. – ckn

+0

Qualche idea con la mia? http://stackoverflow.com/questions/39907625/why-is-accessing-textview-of-a-fragment-inside-activity-throwing-an-error – Si8

1

Frammento

private static FragmentName instance; 

public static synchronized FragmentName getInstance() 
{ 
    return instance; 
} 

@Override 
public void onCreate(@Nullable Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
instance=this; 
.... 
} 

public void methodName() 
{...} 

Attività

FragmentName.getInstance().methodName(); 
Problemi correlati