tri*_*vid 36 java android android-fragments
我有一个片段打开一个Dialogfragment
获取用户输入(一个字符串,和一个整数).如何将这两件事发回片段?
这是我的DialogFragment:
public class DatePickerFragment extends DialogFragment {
String Month;
int Year;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getDialog().setTitle(getString(R.string.Date_Picker));
View v = inflater.inflate(R.layout.date_picker_dialog, container, false);
Spinner months = (Spinner) v.findViewById(R.id.months_spinner);
ArrayAdapter<CharSequence> monthadapter = ArrayAdapter.createFromResource(getActivity(),
R.array.Months, R.layout.picker_row);
months.setAdapter(monthadapter);
months.setOnItemSelectedListener(new OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int monthplace, long id) {
Month = Integer.toString(monthplace);
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
Spinner years = (Spinner) v.findViewById(R.id.years_spinner);
ArrayAdapter<CharSequence> yearadapter = ArrayAdapter.createFromResource(getActivity(),
R.array.Years, R.layout.picker_row);
years.setAdapter(yearadapter);
years.setOnItemSelectedListener(new OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int yearplace, long id) {
if (yearplace == 0){
Year = 2012;
}if (yearplace == 1){
Year = 2013;
}if (yearplace == 2){
Year = 2014;
}
}
public void onNothingSelected(AdapterView<?> parent) {}
});
Button button = (Button) v.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getDialog().dismiss();
}
});
return v;
}
}
Run Code Online (Sandbox Code Playgroud)
我需要在点击按钮之后发送数据 getDialog().dismiss()
以下是需要将数据发送到的片段:
public class CalendarFragment extends Fragment {
int Year;
String Month;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int position = getArguments().getInt("position");
String[] categories = getResources().getStringArray(R.array.categories);
getActivity().getActionBar().setTitle(categories[position]);
View v = inflater.inflate(R.layout.calendar_fragment_layout, container, false);
final Calendar c = Calendar.getInstance();
SimpleDateFormat month_date = new SimpleDateFormat("MMMMMMMMM");
Month = month_date.format(c.getTime());
Year = c.get(Calendar.YEAR);
Button button = (Button) v.findViewById(R.id.button);
button.setText(Month + " "+ Year);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new DatePickerFragment().show(getFragmentManager(), "MyProgressDialog");
}
});
return v;
}
}
Run Code Online (Sandbox Code Playgroud)
因此,一旦用户选择了日期Dialogfragment
,它必须返回月份和年份.
然后,按钮上的文本应更改为用户指定的月份和年份.
Mar*_*ski 85
注意:除了一个或两个Android Fragment特定调用之外,这是用于在松散耦合的组件之间实现数据交换的通用方法配方.您可以安全地使用此方法在字面上交换数据,无论是片段,活动,对话还是应用程序的任何其他元素.
这是食谱:
interface
(即命名MyContract
)包含传递数据的方法的签名,即methodToPassData(... data);
.DialogFragment
fullfils合同(通常意味着实现所需的接口):class MyFragment extends Fragment implements MyContract {....}
DialogFragment
将您的调用设置Fragment
为其目标片段myDialogFragment.setTargetFragment(this, 0);
.这是您稍后将要讨论的对象.DialogFragment
,通过调用getTargetFragment();
并将返回的对象强制转换为您在步骤1中创建的契约接口来获取该调用片段,方法是:MyContract mHost = (MyContract)getTargetFragment();
.Casting让我们确保目标对象实现所需的合同,我们可以期待methodToPassData()
在那里.如果没有,那么你会定期ClassCastException
.这通常不应该发生,除非你做了太多的复制粘贴编码:)如果你的项目使用外部代码,库或插件等,在这种情况下你应该捕获异常并告诉用户即插件不兼容而不是让app崩溃.methodToPassData()
您之前获得的对象:((MyContract)getTargetFragment()).methodToPassData(data);
.如果你onAttach()
已经将目标片段转换并分配给类变量(即mHost
),那么这段代码就是这样mHost.methodToPassData(data);
.您刚刚将对话框中的数据成功传递回调用片段.
bli*_*ard 37
这是另一个没有使用任何接口的配方.只需使用setTargetFragment
和Bundle
在DialogFragment和Fragment之间传递数据.
public static final int DATEPICKER_FRAGMENT = 1; // class variable
Run Code Online (Sandbox Code Playgroud)
1.拨打DialogFragment
如下所示:
// create dialog fragment
DatePickerFragment dialog = new DatePickerFragment();
// optionally pass arguments to the dialog fragment
Bundle args = new Bundle();
args.putString("pickerStyle", "fancy");
dialog.setArguments(args);
// setup link back to use and display
dialog.setTargetFragment(this, DATEPICKER_FRAGMENT);
dialog.show(getFragmentManager().beginTransaction(), "MyProgressDialog")
Run Code Online (Sandbox Code Playgroud)
2.使用额外Bundle
的一个Intent
在DialogFragment
传递什么信息回目标片段.下面的代码中Button#onClick()
的事件DatePickerFragment
传递一个字符串和整数.
Intent i = new Intent()
.putExtra("month", getMonthString())
.putExtra("year", getYearInt());
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, i);
dismiss();
Run Code Online (Sandbox Code Playgroud)
3.使用CalendarFragment
的onActivityResult()
方法来读取值:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case DATEPICKER_FRAGMENT:
if (resultCode == Activity.RESULT_OK) {
Bundle bundle = data.getExtras();
String mMonth = bundle.getString("month", Month);
int mYear = bundle.getInt("year");
Log.i("PICKER", "Got year=" + year + " and month=" + month + ", yay!");
} else if (resultCode == Activity.RESULT_CANCELED) {
...
}
break;
}
}
Run Code Online (Sandbox Code Playgroud)
一个好的技巧是使用ViewModel
和LiveData
方法,这是最好的方法。下面是关于如何在Fragment
s 之间共享数据的代码示例:
class SharedViewModel : ViewModel() {
val selected = MutableLiveData<Item>()
fun select(item: Item) {
selected.value = item
}
}
class MasterFragment : Fragment() {
private lateinit var itemSelector: Selector
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this).get(SharedViewModel::class.java)
} ?: throw Exception("Invalid Activity")
itemSelector.setOnClickListener { item ->
// Update the UI
}
}
}
class DetailFragment : Fragment() {
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this).get(SharedViewModel::class.java)
} ?: throw Exception("Invalid Activity")
model.selected.observe(this, Observer<Item> { item ->
// Update the UI
})
}
}
Run Code Online (Sandbox Code Playgroud)
尝试一下,这些新组件来帮助我们,我认为它比其他方法更有效。
了解更多相关信息:https ://developer.android.com/topic/libraries/architecture/viewmodel
这是一种说明 Marcin 在 kotlin 中实现的答案的方法。
1.创建一个接口,该接口具有在 dialogFragment 类中传递数据的方法。
interface OnCurrencySelected{
fun selectedCurrency(currency: Currency)
}
Run Code Online (Sandbox Code Playgroud)
2.在你的 dialogFragment 构造函数中添加你的界面。
class CurrencyDialogFragment(val onCurrencySelected :OnCurrencySelected) :DialogFragment() {}
Run Code Online (Sandbox Code Playgroud)
3.现在让你的Fragment实现你刚刚创建的接口
class MyFragment : Fragment(), CurrencyDialogFragment.OnCurrencySelected {
override fun selectedCurrency(currency: Currency) {
//this method is called when you pass data back to the fragment
}}
Run Code Online (Sandbox Code Playgroud)
4.然后显示你的dialogFragment你刚刚调用
CurrencyDialogFragment(this).show(fragmentManager,"dialog")
。this
是您将与之交谈的接口对象,用于将数据传递回您的 Fragment。
5.当您想将数据发送回您的 Fragment 时,您只需调用该方法以在您在 dialogFragment 构造函数中传递的接口对象上传递数据。
onCurrencySelected.selectedCurrency(Currency.USD)
dialog.dismiss()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
23772 次 |
最近记录: |