2013-04-16 85 views
68

我對使用片段很新穎。如何傳遞片段之間的值

我只是想構建一個簡單的示例應用程序使用片段。我的情景是,我有兩個活動,每個活動內有一個片段。第一個片段有一個edittext和一個按鈕。第二個片段有一個textview。當我在edittext中輸入名稱並單擊該按鈕時,第二個片段中的textview應顯示在第一個片段的edittext中輸入的名稱。

我能夠將第一個片段的值發送到其活動,然後從該活動發送到第二個活動。現在我該如何在第二個片段中使用這個值。

這裏是Java代碼:::

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; 


    } 

} 

MainActivity.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); 
    } 

} 

SecondActivity.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); 
    } 

} 

我得到下面的異常:::

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 

我如何從包中SecondActivity.java到Fragment_2.Java價值?

+0

請高亮選擇る得到我試過步驟5中的問題 –

回答

157

步驟1。爲了從片段的數據發送到活動

Intent intent = new Intent(getActivity().getBaseContext(), 
         TargetActivity.class); 
       intent.putExtra("message", message); 
       getActivity().startActivity(intent); 

步驟2。要在活動接收該數據:

Intent intent = getIntent(); 
String message = intent.getStringExtra("message"); 

步驟3。從活動的數據發送到另一個活動遵循正常的做法

Intent intent = new Intent(MainActivity.this, 
         TargetActivity.class); 
       intent.putExtra("message", message); 
       startActivity(intent); 

步驟4接收在活動這個數據

 Intent intent = getIntent(); 
    String message = intent.getStringExtra("message"); 

步驟5.從活動可以發送數據到碎片意圖作爲:

Bundle bundle=new Bundle(); 
bundle.putString("message", "From Activity"); 
    //set Fragmentclass Arguments 
Fragmentclass fragobj=new Fragmentclass(); 
fragobj.setArguments(bundle); 

並在片段中接收onCreateView方法OD:

@Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
    Bundle savedInstanceState) { 
      String strtext=getArguments().getString("message"); 

    return inflater.inflate(R.layout.fragment, container, false); 
    } 
+1

的部分,那我打電話從片段和從該活動中選擇項目之後listactivity,我想回來的片段與選定的文件名稱。但它不工作,它在onCreateView上給我Nullpointer異常。任何解決方案,請?這是我的問題http://stackoverflow.com/questions/18208771/nullpointer-exception-while-returning-string-to-fragment-from-activity/18209614?noredirect=1#18209614 – OnkarDhane

+0

我如何把POJO放在這裏? 'bundle.putString(「message」,「From Activity」); ' –

+7

是否有人對如何進行這樣的事情感到厭惡是 –

22

Developers網站:

通常你會想要一個片段與另一個通信,例如改變基於用戶事件的內容。所有片段到片段的通信都是通過相關的活動完成的。兩個碎片不應該直接通信。

您可以藉助其活動在片段之間進行通信。您可以使用this方法在活動和片段之間進行溝通。

請檢查this鏈接。

+0

您給出的第二個鏈接顯示片段之間如何在片段之間進行通信活動。兩者都在不同的活動中時,我該如何溝通? –

2

片段之間的通信相當複雜(我發現聽衆的概念有點難以實現)。

常見的是使用一個「事件總線」抽象這些通信。這是一個第三方庫,負責該通信的爲您服務。

‘奧托’是一個被經常使用要做到這一點,並且可能是值得探討:http://square.github.io/otto/

25

截至開發者網站

經常提到你會想要一個片段與另一個進行通信,例如基於用戶事件改變內容的所有片段 - 。通過關聯進行片段通信活動。兩個碎片不應該直接通信。

片段之間的通信應該通過關聯的Activity完成。

讓我們以下組件:

一個活動主機片段和允許片段通信

FragmentA第一片段,其將發送數據

FragmentB秒片段,其將從接收數據片段A

FragmentA的實現是:

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"); 
       } 
      } 
     }); 
    } 
} 

MainActivity實現:

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(); 
    } 
} 

FragmentB實現:

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)); 
     } 
    } 
} 

我希望這將有助於..

3

首先所有答案都是正確的,您可以通過使用Intent來傳遞除自定義對象之外的數據。如果要傳遞自定義對象,則必須將SerialazableParcelable應用於自定義對象類。我認爲這太複雜了...

因此,如果您的項目很簡單,請嘗試使用DataCache。這爲傳遞數據提供了超級簡單的方法。 編號:https://github.com/kimkevin/AndroidDataCache

該設置,查看或活動或片段將發送數據

DataCache.getInstance().push(obj); 

2-獲取數據的任何地方像下面

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 
2

傳遞參數片段之間。 這是一個相當晚的回答這個問題,但它可以幫助別人! 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(); 

然後你Fragment_2.java你可以得到PARAMATERS通常在您onActivityCreated e.g

Intent intent = getActivity().getIntent(); 
    if (intent.getExtras() != null) { 
     String name =intent.getStringExtra("name"); 
    } 
13

//在Fragment_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(); 

//在Fragment_2.java中

Bundle bundle = this.getArguments(); 

if(bundle != null){ 
    // handle your code here. 
} 

希望這對你有所幫助。

+0

乾淨的答案顯示的主要觀點。使用'putString'(或'putInt')就是答案! –

-1

從來就做的東西很容易像我這樣begginers .. 我在activity_main.xml中取得一個TextView,把

id=index 
visibility=invisible 

然後我從第一個片段得到這個TextView的

index= (Textview) getActivity().findviewbyid(R.id.index) 
index.setText("fill me with the value") 

,然後在第二個片段,我得到的價值

index= (Textview) getActivity().findviewbyid(R.id.index) 
String get_the_value= index.getText().toString(); 

希望它有助於!

0

這個簡單的實現有助於以簡單的方式在片段之間傳遞數據。 想你想從 'Frgment1' 數據傳遞給 'Fragment2'

在片段1(設置數據發送)

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(); 

在Fragment2 onCreateView方法(GET parameteres)

String value = this.getArguments().getString("key");//get your parameters 
Toast.makeText(getActivity(), value+" ", Toast.LENGTH_LONG).show();//show data in tost 
1

傳從片段到另一片段的數據

  • 從第一個片段

    // 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(); 
    
  • 在第二塊碎片

    @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 
        } 
    } 
    
0

我認爲解決這個問題的好辦法是使用自定義的界面。

比方說你有兩個片段(A和B),它們是相同的活性的內並且希望從A將數據發送到B.

接口:

public interface OnDataSentListener{ 
    void onDataSent(Object data); 
} 

活動:

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; 
      } 
     } 

片段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; 
    } 
} 

片段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 
      } 
     }); 
    } 
}