[英]How to send data from fragment to fragment within same fragment activity?
[英]How to send fragment edittext data to activity without buttons in the fragment
我正在使用片段和 viewpager 制作一個應用程序,它將用戶數據發送到主要活動。 數據將從多個片段中收集,並在提交按鈕(包含在主活動中)被按下到活動時發送。 示例截圖:
我不確定如何獲取片段編輯文本數據。 我嘗試在 onClick 偵聽器中使用 R.findViewById 獲取提交按鈕,但似乎我錯過了一個重要步驟。 我嘗試查看視頻/教程,但我只能找到在片段中按下按鈕時獲取數據的適用視頻/教程,或者相反的視頻/教程(片段從活動中獲取數據)。
這是我的代碼:formActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.google.android.material.tabs.TabLayout;
public class FormActivity extends AppCompatActivity {
private static final String TAG = "PROCESS";
TabLayout tabLayout;
ViewPager viewPager;
//or set to 0 and change it dynamically in the onPageSelected method
private int numFrags = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_formactivity);
viewPager = findViewById(R.id.viewPager);
tabLayout = findViewById(R.id.tabLayout);
getTabs();
//Add onPageChangeListener to get the position of the current tab and change the button text based on the position
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
Button back = findViewById(R.id.backButton);
Button next = findViewById(R.id.nextButton);
Button mainReturn = findViewById(R.id.mainReturn);
Button submit = findViewById(R.id.submitButton);
PagerAdapter adapter = viewPager.getAdapter();
//numFrags = viewPager.getAdapter().getCoBunt() -1; - dynamically get new frags
if (position == 0) {
back.setVisibility(View.GONE);
next.setVisibility(View.VISIBLE);
mainReturn.setVisibility(View.VISIBLE);
}
else if (adapter != null && position == numFrags) {
back.setVisibility(View.VISIBLE);
next.setVisibility(View.GONE);
submit.setVisibility(View.VISIBLE);
}
else {
back.setVisibility(View.VISIBLE);
next.setVisibility(View.VISIBLE);
mainReturn.setVisibility(View.GONE);
submit.setVisibility(View.GONE);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
//Add fragments to viewPager using the object ViewPagerAdapter
public void getTabs(){
final ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
new Handler().post(new Runnable() {
@Override
public void run() {
viewPagerAdapter.addFragment(oneFragment.getInstance(),null); // this line can cause crashes
viewPagerAdapter.addFragment(twoFragment.getInstance(),null); // this line can cause crashes
viewPagerAdapter.addFragment(threeFragment.getInstance(),null); // this line can cause crashes
viewPager.setAdapter(viewPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
}
});
}
//METHODS FOR THE BUTTON LISTENERS
public void goBack(View view) {
viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
}
public void goNext(View view) {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
}
public void submitFormEntries(View view) {
Log.d(TAG, "returnToMainMenu: ");
}
public void returnToMainMenu(View view) {
Log.d(TAG, "returnToMainMenu: ");
}
}
查看PagerAdapter.java
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragmentList = new ArrayList<>(); // this line can cause crashes
private List<String> stringList = new ArrayList<>();
public ViewPagerAdapter(@NonNull FragmentManager fm) {
super(fm);
}
@NonNull
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return stringList.get(position);
}
public void addFragment(Fragment fragment, String title){
fragmentList.add(fragment); // this line can cause crashes
stringList.add(title);
}
}
oneFragment.java
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class oneFragment extends Fragment {
public static oneFragment getInstance(){
oneFragment oneFragment = new oneFragment();
return oneFragment;
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.page_one, container,false);
return view;
}
}
activity_formactivity.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context=".FormActivity">
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
android:id="@+id/backButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:onClick="goBack"
android:visibility="gone"/>
<Button
android:id="@+id/mainReturn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mainReturn"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:onClick="returnToMainMenu"
android:visibility="visible"/>
<Button
android:id="@+id/nextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/next"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:onClick="goNext"/>
<Button
android:id="@+id/submitButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/submit"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:onClick="submitFormEntries"
android:visibility="gone"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tabBackground="@drawable/tab_selector"
app:tabIndicatorHeight="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>
page_one.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">
<TextView
android:id="@+id/titleOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="@string/title_one"
android:textColor="@color/colorPrimaryDark"
android:textSize="32sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/questionOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/questionOne"
android:textColor="@color/colorPrimaryDark"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@+id/descriptionOne"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/descriptionOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/descriptionOne"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@+id/answerOne"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<EditText
android:id="@+id/answerOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/answerHintOne"
android:inputType="textMultiLine"
android:maxLines="4"
android:minLines="4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
我很新,所以任何替代建議以及答案也將不勝感激。
使用捆綁包。 這是一個例子:
Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);
Bundle 為許多數據類型提供了 put 方法。 看到這個
然后在您的片段中,使用以下命令檢索數據(例如在 onCreate() 方法中):
Bundle bundle = this.getArguments();
if (bundle != null) {
int myInt = bundle.getInt(key, defaultValue);
}
在 bundle.setArguments 中設置第一個片段的值,第二個片段的 onCreate() 使用第二個片段中的 bundle.getInt() 獲取值,與具有第一個片段和第二個片段的值的 bundle.setArguemnts 相同,因此在第 3 個片段中,您將獲得以下值拳頭和第二個碎片。
片段 1:
Bundle bundle = new Bundle();
bundle.putString("FRAGEMNT1", "VALUE FRAGEMENT 1");
fragment.setArguments(bundle);
在片段 2 的 onCrete()
Bundle bundle = this.getArguments();
if (bundle != null) {
String frag1Value = bundle.getString("FRAGEMNT1");
}
現在將兩個值都放在片段 2 中
Bundle bundle = new Bundle();
bundle.putString("FRAGEMNT1", "VALUE FRAGEMENT 1");
bundle.putString("FRAGEMNT2, "VALUE FRAGEMENT 2);
fragment.setArguments(bundle);
在片段 3 onCrete()
Bundle bundle = this.getArguments();
if (bundle != null) {
String frag1Value = bundle.getString("FRAGEMNT1");
String frag2Value = bundle.getString("FRAGEMNT2");
}
現在將兩個值都放在片段 3 中
Bundle bundle = new Bundle();
bundle.putString("FRAGEMNT1", "VALUE FRAGEMENT 1");
bundle.putString("FRAGEMNT2, "VALUE FRAGEMENT 2);
bundle.putString("FRAGEMNT3, "VALUE FRAGEMENT 3");
fragment.setArguments(bundle);
現在在 activit 的 onCrete
Bundle bundle = this.getArguments();
if (bundle != null) {
String frag1Value=bundle.getString("FRAGEMNT1");
String frag2Value=bundle.getString("FRAGEMNT2");
String frag3Value=bundle.getString("FRAGEMNT3");
}
您可以使用 SharedPreferences 來存儲數據並在需要時檢索數據。 例子:
在 Preference 中設置值:
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putString("key", "your answer");
editor.apply();
從首選項中檢索數據:
SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
String answer= prefs.getString("key", "");
How about using ViewModel
that is tied to FormActivity
and save edit text value there https://developer.android.com/topic/libraries/architecture/viewmodel?gclid=Cj0KCQiA3NX_BRDQARIsALA3fIJFaBMomx-KDhghEHZghVGwGaafvDwMpGzFxQFGm3M3_e0lv9Bzt1UaAoq7EALw_wcB&gclsrc=aw.ds
class FormViewModel : ViewModel() {
val answers: Map<String, String> = mutableMapOf()
}
從片段
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
val viewmodel = ViewModelProviders.of(requireActivity()).get(FormViewModel::class.java)
viewModel.answer["SOME_KEY_HERE"] = s.toString()
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
})
從活動中,您可以訪問諸如
ViewModelProvider.of(this).get(FormViewModel::class.java).answer
抱歉,我用 kotlin 寫的,但你應該可以理解
實現常規 FragmentPagerAdapter 的正確方法是:
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public Fragment getItem(int position) {
if(position == 0) return new RulesFragment();
if(position == 1) return new TreeFragment();
if(position == 2) return new PredictionFragment();
throw new IllegalStateException("Unexpected position " + position);
}
@Override
public int getCount() {
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
if(position == 0) return "TREE RULES";
if(position == 1) return "REGRESSION TREE";
if(position == 2) return "PREDICTION";
throw new IllegalStateException("Unexpected position " + position);
}
}
要獲取對 ViewPager 創建的 Fragment 的引用,請使用以下findFragmentByTag
方案:
Fragment fragment = supportFragmentManager.findFragmentByTag("android:switcher:" + viewPager.getId() + ":" + fragmentPosition)
在多個片段之間進行通信的正確方法是使用范圍為共享 scope 的 ViewModel(在這種情況下,可能是 Activity)。
為此,請參閱https://developer.android.com/codelabs/kotlin-android-training-view-model#0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.