gpt4 book ai didi

android - FragmentPagerAdapter 在方向更改时不恢复 fragment

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:02:47 25 4
gpt4 key购买 nike

编辑:我发现 Activity 正在保存实例,但 Fragments 保存的数据没有达到 Activity savedInstanceState。我将当前时间保存在 outState 中,但它并没有一直向上,因为该 Activity 当时在其 SavedInstanceState 中没有任何内容,如果我将其打印到 logcat,则该时间返回“null”。 ..

我正在构建一个内置了倒计时计时器的应用程序。计时器的基本托管 Activity 是一个 FragmentActivity,它托管一个 FragementPagerAdapter,它在代码中膨胀两个 fragment (我没有为 fragment 提供 ID在 XML 中,因为它们未定义为 .xml 中的 fragment )。一切都很好,直到方向改变,然后 Activity 看起来像它与旧 fragment 失去联系,只是选择创建新 fragment 。这意味着任何当前倒计时都会丢失,并且任何选择的时间也会在配置更改时丢失。我需要继续计数(如果它开始了)和当前显示的任何数字....

我知道适配器应该自己处理这些事情,我在 OnCreate 和 OnCreateView 中都设置了 SetRetainInstance(true)。

我在 fragment 代码中加入了钩子(Hook),以便在 saveInstanceState 不为 null 时通知我,所以至少我知道发生了什么,但实例似乎始终为 NULL,并且它从头开始创建...总是.

其他一些解决方案让我覆盖了 instantiateItem,但它似乎只用于重置回调,其他解决方案更改 list 中的设置(不赞成)....其他解决方案在我看来就像我已经设置好了东西对...但很明显,我一路上搞砸了。我只提供 FragmentActivity、FragementPagerAdapter 的代码和一些 Fragment 代码,因为我不想用可能不是问题的代码向帖子发送垃圾邮件。

fragment Activity

public class Timer_Main extends FragmentActivity {
ViewPager pager;
Timer_Pager mAdapter;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timer_pager);

mAdapter = new Timer_Pager(this, getSupportFragmentManager());

pager = (ViewPager) findViewById(R.id.timer_pager_display);
pager.setAdapter(mAdapter);

}

public static String getTitle(Context ctxt, int position) {
// TODO Auto-generated method stub
return null;
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("pageItem", pager.getCurrentItem());

}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);

}
}

FragementPagerAdapter

public class Timer_Pager extends FragmentPagerAdapter{
Context ctxt = null;
public Timer_Pager(Context ctxt, FragmentManager fm) {
super(fm);
this.ctxt = ctxt;
}


@Override
public Fragment getItem(int position) {

switch (position) {
case 0: {
return(Countdown_Fragment.newInstance());
}
case 1:
return(Countup_Fragment.newInstance());
}
return null;
}

@Override
public String getPageTitle(int position) {

switch (position) {
case 0:
return(String.format(ctxt.getString(R.string.Countdown_label)));
case 1:
return(String.format(ctxt.getString(R.string.Countup_label)));
}
return null;
}

@Override
public int getCount() {
// doing only three pages, right now...one for countdown, one for countup, and one for Tabata.
return 2;
}

private static String makeFragmentName(int viewId, int position)
{
return "android:switcher:" + viewId + ":" + position;
}
}

Fragment 中有更多的代码,所以我将把应该是问题的核心的代码放入其中......如果需要更多,我会拼接进去。

public class Countdown_Fragment extends Fragment implements OnClickListener {
Calendar CountdownTime = Calendar.getInstance();
static AutoResizeTextView tv;
static ImageButton HoursUp;
static ImageButton HoursDown;
static ImageButton MinutesUp;
static ImageButton MinutesDown;
static ImageButton SecondsUp;
static ImageButton SecondsDown;
static ImageButton Reset;
static ImageButton StartPausecount;
static ImageButton Stopcount;
static Boolean Arewecounting = false;
static Boolean Arewecountingdown = false;
static AutoResizeTextView ThreetwooneGO;
static MyCountdownTimer Countdown_Timer_Activity;
ThreetwooneCount Start_countdown;
static Long MillstoPass;

static Countdown_Fragment newInstance() {

Countdown_Fragment frag = new Countdown_Fragment();
return (frag);
}

@Override
public void onSaveInstanceState(Bundle outState) {

outState.putString("CurrentTimer", (String) tv.getText());
Log.v("status", "saved fragment state" + tv.getText());
super.onSaveInstanceState(outState);
}

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);

}

@Override
public void onCreate(Bundle savedInstanceState) {
setRetainInstance(true);
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

setRetainInstance(true);
View result = inflater.inflate(R.layout.countdown_timer_layout,
container, false);
tv = (AutoResizeTextView) result.findViewById(R.id.timer_textview);
tv.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
new TimePickerDialog(getActivity(), t, 0, 0, true).show();
}
});
if (savedInstanceState != null) {
Log.v("status", "fragment is NOT empty");
tv.setText(savedInstanceState.getString("CurrentTimer",
tv.toString()));
} else {
Log.v("status", "fragment is empty");
// tv.setText("00:00:00");

}
tv.resizeText();

ThreetwooneGO = (AutoResizeTextView) result
.findViewById(R.id.timer_countdown_text);

HoursUp = (ImageButton) result.findViewById(R.id.hours_up);
HoursDown = (ImageButton) result.findViewById(R.id.hours_down);
MinutesUp = (ImageButton) result.findViewById(R.id.minutes_up);
MinutesDown = (ImageButton) result.findViewById(R.id.minutes_down);
SecondsUp = (ImageButton) result.findViewById(R.id.seconds_up);
SecondsDown = (ImageButton) result.findViewById(R.id.seconds_down);
Reset = (ImageButton) result.findViewById(R.id.reset);
StartPausecount = (ImageButton) result
.findViewById(R.id.startpausecount);
Stopcount = (ImageButton) result.findViewById(R.id.stopcount);

HoursUp.setOnClickListener(this);
HoursDown.setOnClickListener(this);
SecondsUp.setOnClickListener(this);
SecondsDown.setOnClickListener(this);
MinutesUp.setOnClickListener(this);
MinutesDown.setOnClickListener(this);
Reset.setOnClickListener(this);
StartPausecount.setOnClickListener(this);
Stopcount.setOnClickListener(this);

return (result);
}

public void chooseTime(View v) {
new TimePickerDialog(getActivity(), t, 0, 0, true).show();
}

TimePickerDialog.OnTimeSetListener t = new TimePickerDialog.OnTimeSetListener() {
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
CountdownTime.set(Calendar.HOUR_OF_DAY, hourOfDay);
CountdownTime.set(Calendar.MINUTE, minute);
CountdownTime.set(Calendar.SECOND, 0);
CountdownTime.set(Calendar.MILLISECOND, 0);

updateLabel();
}
};

private void updateLabel() {

String entiretime;
entiretime = String.format("%tT", CountdownTime);
tv.setText(entiretime);
}

这是我用于倒计时的计时器....

public class MyCountdownTimer {

private long millisInFuture;
private long countDownInterval;
Countdown_Fragment ctxt;
AutoResizeTextView Timer_edit;
private volatile boolean IsStopped = false;

public MyCountdownTimer(long pMillisInFuture, long pCountDownInterval,
AutoResizeTextView Artv) {
this.millisInFuture = pMillisInFuture;
this.countDownInterval = pCountDownInterval;

Timer_edit = Artv;

}

public void Start() {

final Handler handler = new Handler();
final Runnable counter = new Runnable() {

public void run() {
if (IsStopped == false) {
if (millisInFuture <= 0) {
Countdown_Fragment.done_counting();
} else {
long sec = millisInFuture / 1000;
Timer_edit.setText(String.format("%02d:%02d:%02d",
sec / 3600, (sec % 3600) / 60, (sec % 60)));
millisInFuture -= countDownInterval;
handler.postDelayed(this, countDownInterval);
}
}
}
};

handler.postDelayed(counter, countDownInterval);
}

public void Cancel() {
IsStopped = true;
Timer_edit = null;
Log.v("status", "Main Timer cancelled");
// this.ctxt = null;

}
public long whatisourcount(){
return(millisInFuture);
}
}

最佳答案

事实证明,RetainInstance 导致其自身与 ViewPager/Adapter/FragmentManager 之间发生冲突。删除它会导致寻呼机正确重建 fragment ,包括我拥有的 TextView,而以前没有。我也开始在 OnCreateView 中收到一个 Bundle,在 RetainInstance 设置为 True 之前它始终为 null。

我必须删除 RetainInstance 并利用 OnSaveInstanceState 和 OnCreateView 传入 Fragment 销毁前的当前状态,然后在 OnCreateView 中重新创建它以将 Fragment 重置为销毁前的状态。

我希望我用来倒计时的 Runnable 能够存活下来,或者我能够重新附加它,但我找不到办法。我必须以毫秒为单位保存当前计数,然后传回 fragment 以从中断处继续。这没什么大不了的,但我很好奇你是否真的能重新连接所有这些东西。 Runnable 在配置更改后仍然继续,但它不再更新 UI 上的任何内容,因此当我在 OnSaveInstanceState 中时,我尝试取消回调并将其清空。

我还阅读了一些项目,其中我只需要将 RetainInstance 用于附加了 AsyncTask 的项目或其他类似项目....否则,只需在代码中重建它即可。

关于android - FragmentPagerAdapter 在方向更改时不恢复 fragment ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18425646/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com