Jak przekazywać wartości między fragmentami
Jestem całkiem nowy w używaniu fragmentów.
Próbuję tylko zbudować prostą przykładową aplikację, która wykorzystuje fragmenty. Mój scenariusz jest taki, że mam dwie czynności z jednym fragmentem wewnątrz każdej czynności. Pierwszy fragment ma edytowany tekst i przycisk. Drugi fragment ma widok tekstu. Gdy wprowadzę nazwę w edytowanym tekście i kliknę przycisk, textview w drugim fragmencie powinien wyświetlać nazwę wprowadzoną w edytowanym tekście pierwszego fragmentu.
Udało mi się wysłać wartość od pierwszego fragmentu do jego aktywności, a następnie od tej aktywności do drugiej aktywności. Teraz Jak mogę użyć tej wartości wewnątrz drugiego fragmentu.
Oto Kod Javy:::
package com.example.fragmentexample;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class Fragment_1 extends Fragment{
OnFragmentChangedListener mCallback;
// Container Activity must implement this interface
public interface OnFragmentChangedListener {
public void onButtonClicked(String name);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnFragmentChangedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.fragment_fragment_1, container, false);
final EditText edtxtPersonName_Fragment = (EditText) view.findViewById(R.id.edtxtPersonName);
Button btnSayHi_Fragment = (Button) view.findViewById(R.id.btnSayHi);
btnSayHi_Fragment.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String name = edtxtPersonName_Fragment.getText().toString();
FragmentManager fm = getFragmentManager();
Fragment_2 f2 = (Fragment_2) fm.findFragmentById(R.id.fragment_content_2);
Activity activity = getActivity();
if(activity != null)
{
Toast.makeText(activity, "Say&ing Hi in Progress...", Toast.LENGTH_LONG).show();
}
if(f2 != null && f2.isInLayout())
{
f2.setName(name);
}
else
{
mCallback.onButtonClicked(name);
}
}
});
return view;
}
}
Główna aktywność.Java
package com.example.fragmentexample;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Choreographer.FrameCallback;
import android.view.Menu;
public class MainActivity extends Activity implements Fragment_1.OnFragmentChangedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public void onButtonClicked(String name) {
// TODO Auto-generated method stub
Intent i = new Intent(this, SecondActivity.class);
i.putExtra("", name);
startActivity(i);
}
}
Druga aktywność.Java
package com.example.fragmentexample;
import android.app.Activity;
import android.os.Bundle;
public class SecondActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Bundle b = getIntent().getExtras();
Fragment_2 f2 = new Fragment_2();
f2.setArguments(b);
}
}
Fragment_2.Java
package com.example.fragmentexample;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class Fragment_2 extends Fragment{
View view;
TextView txtName;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
view = inflater.inflate(R.layout.fragment_fragment_2, container, false);
// Exception at this line
String name = getArguments().getString("message");
txtName = (TextView) view.findViewById(R.id.txtViewResult);
txtName.setText(name);
return view;
}
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
}
public void setName(String name)
{
txtName.setText("Hi " + name);
}
}
Dostaję następujący wyjątek:::
04-16 18:10:24.573: E/AndroidRuntime(713): FATAL EXCEPTION: main
04-16 18:10:24.573: E/AndroidRuntime(713): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.fragmentexample/com.example.fragmentexample.SecondActivity}: android.view.InflateException: Binary XML file line #8: Error inflating class fragment
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1815)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1831)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.ActivityThread.access$500(ActivityThread.java:122)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1024)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.os.Handler.dispatchMessage(Handler.java:99)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.os.Looper.loop(Looper.java:132)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.ActivityThread.main(ActivityThread.java:4123)
04-16 18:10:24.573: E/AndroidRuntime(713): at java.lang.reflect.Method.invokeNative(Native Method)
04-16 18:10:24.573: E/AndroidRuntime(713): at java.lang.reflect.Method.invoke(Method.java:491)
04-16 18:10:24.573: E/AndroidRuntime(713): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
04-16 18:10:24.573: E/AndroidRuntime(713): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
04-16 18:10:24.573: E/AndroidRuntime(713): at dalvik.system.NativeStart.main(Native Method)
04-16 18:10:24.573: E/AndroidRuntime(713): Caused by: android.view.InflateException: Binary XML file line #8: Error inflating class fragment
04-16 18:10:24.573: E/AndroidRuntime(713): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:688)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.view.LayoutInflater.rInflate(LayoutInflater.java:724)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.view.LayoutInflater.inflate(LayoutInflater.java:391)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.view.LayoutInflater.inflate(LayoutInflater.java:347)
04-16 18:10:24.573: E/AndroidRuntime(713): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:223)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.Activity.setContentView(Activity.java:1786)
04-16 18:10:24.573: E/AndroidRuntime(713): at com.example.fragmentexample.SecondActivity.onCreate(SecondActivity.java:13)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.Activity.performCreate(Activity.java:4397)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1048)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1779)
04-16 18:10:24.573: E/AndroidRuntime(713): ... 11 more
04-16 18:10:24.573: E/AndroidRuntime(713): Caused by: java.lang.NullPointerException
04-16 18:10:24.573: E/AndroidRuntime(713): at com.example.fragmentexample.Fragment_2.onCreateView(Fragment_2.java:24)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:754)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:956)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1035)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.app.Activity.onCreateView(Activity.java:4177)
04-16 18:10:24.573: E/AndroidRuntime(713): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:664)
04-16 18:10:24.573: E/AndroidRuntime(713): ... 21 more
Jak uzyskać wartość z pakietu w SecondActivity.java do Fragmentu_2.Java?
12 answers
Krok 1 . aby wysłać dane z fragmentu do aktywności
Intent intent = new Intent(getActivity().getBaseContext(),
TargetActivity.class);
intent.putExtra("message", message);
getActivity().startActivity(intent);
Krok 2 . aby otrzymać te dane w aktywności:
Intent intent = getIntent();
String message = intent.getStringExtra("message");
Krok 3 . aby wysłać dane z aktywności do innej aktywności, postępuj zgodnie z normalnym podejściem
Intent intent = new Intent(MainActivity.this,
TargetActivity.class);
intent.putExtra("message", message);
startActivity(intent);
Krok 4 aby otrzymać te dane w aktywności
Intent intent = getIntent();
String message = intent.getStringExtra("message");
Punkt 5. z aktywności można wysyłać dane do fragmentu z intencją jako:
Bundle bundle=new Bundle();
bundle.putString("message", "From Activity");
//set Fragmentclass Arguments
Fragmentclass fragobj=new Fragmentclass();
fragobj.setArguments(bundle);
I otrzymywanie we fragmencie w fragmencie oncreateview metoda:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext=getArguments().getString("message");
return inflater.inflate(R.layout.fragment, container, false);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-16 13:20:00
Jak zaznaczono na stronie dewelopera
Często będziesz chciał, aby jeden Fragment komunikował się z innym, na przykład, aby zmienić zawartość na podstawie zdarzenia użytkownika. Cała komunikacja Fragment-Fragment odbywa się za pośrednictwem powiązanej aktywności. Dwa fragmenty nigdy nie powinny komunikować się bezpośrednio.
Komunikacja między fragmentami powinna odbywać się poprzez powiązane działanie.
Niech będą następujące składniki:
Aktywność hostuje fragmenty i zezwala na komunikację fragmentów
FragmentA pierwszy fragment, który wyśle dane
FragmentB drugi fragment, który otrzyma dane z FragmentA
Implementacja fragmentu to:
public class FragmentA extends Fragment
{
DataPassListener mCallback;
public interface DataPassListener{
public void passData(String data);
}
@Override
public void onAttach(Context context)
{
super.onAttach(context);
// This makes sure that the host activity has implemented the callback interface
// If not, it throws an exception
try
{
mCallback = (OnImageClickListener) context;
}
catch (ClassCastException e)
{
throw new ClassCastException(context.toString()+ " must implement OnImageClickListener");
}
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
// Suppose that when a button clicked second FragmentB will be inflated
// some data on FragmentA will pass FragmentB
// Button passDataButton = (Button).........
passDataButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (view.getId() == R.id.passDataButton) {
mCallback.passData("Text to pass FragmentB");
}
}
});
}
}
Główna implementacja to:
public class MainActivity extends ActionBarActivity implements DataPassListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.container) != null) {
if (savedInstanceState != null) {
return;
}
getFragmentManager().beginTransaction()
.add(R.id.container, new FragmentA()).commit();
}
}
@Override
public void passData(String data) {
FragmentB fragmentB = new FragmentB ();
Bundle args = new Bundle();
args.putString(FragmentB.DATA_RECEIVE, data);
fragmentB .setArguments(args);
getFragmentManager().beginTransaction()
.replace(R.id.container, fragmentB )
.commit();
}
}
Implementacja fragmentu to:
public class FragmentB extends Fragment{
final static String DATA_RECEIVE = "data_receive";
TextView showReceivedData;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_B, container, false);
showReceivedData = (TextView) view.findViewById(R.id.showReceivedData);
}
@Override
public void onStart() {
super.onStart();
Bundle args = getArguments();
if (args != null) {
showReceivedData.setText(args.getString(DATA_RECEIVE));
}
}
}
Mam nadzieję, że to pomoże..Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-18 04:12:03
From Developers website:
Często będziesz chciał, aby jeden Fragment komunikował się z innym, na przykład, aby zmienić zawartość na podstawie zdarzenia użytkownika. Cała komunikacja Fragment-Fragment odbywa się za pośrednictwem powiązanej aktywności. Dwa fragmenty nigdy nie powinny komunikować się bezpośrednio.
Możesz komunikować się między fragmentami za pomocą jego aktywności. Możesz komunikować się między aktywnością i fragmentami za pomocą tego podejścia .
Proszę sprawdzić ten link również.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-16 12:10:03
/ / W Części_1.java
Bundle bundle = new Bundle();
bundle.putString("key","abc"); // Put anything what you want
Fragment_2 fragment2 = new Fragment_2();
fragment2.setArguments(bundle);
getFragmentManager()
.beginTransaction()
.replace(R.id.content, fragment2)
.commit();
/ / W Części_2.java
Bundle bundle = this.getArguments();
if(bundle != null){
// handle your code here.
}
Mam nadzieję, że to ci pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-27 10:11:49
Po Pierwsze wszystkie odpowiedzi są poprawne, możesz przekazać dane z wyjątkiem obiektów niestandardowych za pomocą Intent
. Jeśli chcesz przekazać niestandardowe obiekty, musisz zaimplementować Serialazable
lub Parcelable
do swojej niestandardowej klasy obiektów. Myślałem, że to zbyt skomplikowane...
Więc jeśli twój projekt jest prosty, spróbuj użyć DataCache
. Zapewnia to bardzo prosty sposób przekazywania danych.
Ref: Github project CachePot
1- ustaw to na widok, aktywność lub Fragment, który wyśle DANE
DataCache.getInstance().push(obj);
2- Pobierz dane w dowolnym miejscu, jak poniżej
public class MainFragment extends Fragment
{
private YourObject obj;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
obj = DataCache.getInstance().pop(YourObject.class);
}//end onCreate()
}//end class MainFragment
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-16 11:09:44
Komunikacja między fragmentami jest dość skomplikowana (uważam, że koncepcja słuchaczy jest trochę trudna do wdrożenia).
Powszechnie używa się 'szyny zdarzeń" do abstrakcji tych komunikatów. Jest to biblioteka 3rd party, która dba o tę komunikację dla Ciebie.
'Otto' jest takim, który jest często używany do tego celu i może warto zajrzeć: http://square.github.io/otto/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-16 12:32:28
Przekazywanie argumentów między fragmentami.
Jest to dość późno, aby odpowiedzieć na to pytanie, ale to może komuś pomóc!
Fragment_1.java
Bundle i = new Bundle();
i.putString("name", "Emmanuel");
Fragment_1 frag = new Fragment_1();
frag.setArguments(i);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame
, new Fragment_2())
.commit();
Wtedy w Twoim Fragment_2.java
możesz uzyskać parametry normalnie w swoim onActivityCreated
e. g
Intent intent = getActivity().getIntent();
if (intent.getExtras() != null) {
String name =intent.getStringExtra("name");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-08 21:10:45
Ta prosta implementacja pomaga w prosty sposób przekazywać dane między fragmentami. Myślę, że chcesz przekazać dane z 'Frgment1 ' do'Fragment2'
In Fragment1 (Set data to send)
Bundle bundle = new Bundle();
bundle.putString("key","Jhon Doe"); // set your parameteres
Fragment2 nextFragment = new Fragment2();
nextFragment.setArguments(bundle);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_drawer, nextFragment).commit();
In Fragment2 oncreateview method (get parameteres)
String value = this.getArguments().getString("key");//get your parameters
Toast.makeText(getActivity(), value+" ", Toast.LENGTH_LONG).show();//show data in tost
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-28 08:53:07
Przekazywanie danych z fragmentu do innego fragmentu
-
Z pierwszego fragmentu
// Set data to pass MyFragment fragment = new MyFragment(); //Your Fragment Bundle bundle = new Bundle(); bundle.putInt("year", 2017) // Key, value fragment.setArguments(bundle); // Pass data to other Fragment getFragmentManager() .beginTransaction() .replace(R.id.content, fragment) .commit();
-
Na Drugim Fragmencie
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle bundle = this.getArguments(); if (bundle != null) { Int receivedYear = bundle.getInt("year", ""); // Key, default value } }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-19 10:36:34
Najnowsze rozwiązanie do przesyłania danych między fragmentami może być zaimplementowane przy użyciu komponentów architektonicznych Androida, takich jak ViewModel i LiveData. Dzięki temu rozwiązaniu nie musisz definiować interfejsu do komunikacji i możesz uzyskać zalety korzystania z viewmodel, takie jak przetrwanie danych ze względu na zmiany konfiguracji.
W tym rozwiązaniu fragmenty zaangażowane w komunikację dzielą ten sam obiekt viewmodel, który jest związany z cyklem życia ich aktywności. Obiekt modelu widoku zawiera obiekt livedata. Jeden fragment ustawia dane do przekazania na obiekcie livedata, a drugi fragment obserwatorów livedata zmienia i odbiera dane.
Oto pełny przykład http://www.zoftino.com/passing-data-between-android-fragments-using-viewmodel
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-19 04:02:49
Myślę, że dobrym sposobem na rozwiązanie tego problemu jest użycie niestandardowego interfejsu.
Powiedzmy, że masz dwa fragmenty (A i B), które są wewnątrz tej samej aktywności i chcesz wysłać dane z A do B.
Interfejs:
public interface OnDataSentListener{
void onDataSent(Object data);
}
Aktywność:
public class MyActivity extends AppCompatActivity{
private OnDataSentListener onDataSentListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity);
FragmentTransaction trans = getFragmentManager().beginTransaction();
FragmentA fa = new FragmentA();
FragmentB fb = new FragmentB();
fa.setOnDataSentListener(new Listeners.OnDataSentListener() {
@Override
public void onDataSent(Object data) {
if(onDataSentListener != null) onDataSentListener.onDataSent(data);
}
});
transaction.add(R.id.frame_a, fa);
transaction.add(R.id.frame_b, fb);
transaction.commit();
}
public void setOnDataSentListener(OnDataSentListener listener){
this.onDataSentListener = listener;
}
}
Fragment A:
public class FragmentA extends Fragment{
private OnDataSentListener onDataSentListener;
private void sendDataToFragmentB(Object data){
if(onDataSentListener != null) onDataSentListener.onDataSent(data);
}
public void setOnDataSentListener(OnDataSentListener listener){
this.onDataSentListener = listener;
}
}
Fragment B:
public class FragmentB extends Fragment{
private void initReceiver(){
((MyActivity) getActivity()).setOnDataSentListener(new OnDataSentListener() {
@Override
public void onDataSent(Object data) {
//Here you receive the data from fragment A
}
});
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-22 12:17:29
Zrobiłem coś naprawdę łatwego dla początkujących jak ja.. zrobiłem textview w moim activity_main.xml i put
id=index
visibility=invisible
Potem dostaję ten tekst z pierwszego fragmentu
index= (Textview) getActivity().findviewbyid(R.id.index)
index.setText("fill me with the value")
A następnie w drugim fragmencie otrzymuję wartość
index= (Textview) getActivity().findviewbyid(R.id.index)
String get_the_value= index.getText().toString();
Mam nadzieję, że to pomoże!Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-27 20:11:20