- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我创建了一个自定义 View ,它是 RelativeLayout
的子类.该 View 是 Fragment
的一部分设置为保留其实例状态。我想在设备方向改变时保存状态信息(只有一个 bool 值),所以我实现了 onSaveInstanceState
和 onRestoreInstanceState
使用我的自定义扩展名 BaseSavedState
. Fragment
都不是,也不是 Activity
已经实现了任何处理保存/恢复实例状态的事情。当我更改设备方向时,它会保存状态,使用保存的状态重新创建 View ,然后再次不调用 onRestoreInstanceState
重新创建它.
事件的顺序是这样的,showingProgress
是我要保存的 bool 值:
View#1 (onSaveInstanceState) showingProgress=true
View#2 (ctor) showingProgress=false
View#2 (onFinishInflate)
View#2 (onRestoreInstanceState) showingProgress=true
View#2 (showProgress)
View#2 (onSaveInstanceState) showingProgress=true
View#3 (ctor) showingProgress=false
View#3 (onFinishInflate)
在那之后, View 被重建,但是因为onRestoreInstanceState
永远不会为 View #3 调用,它始终处于初始状态。
为什么它会重新创建 View 两次?如何防止第二个 View 再次重新创建,或将保存的状态分别传递给第三个 View ?
编辑:
Activity 相关部分
private Fragment currentFragment = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.single_fragment);
getSupportActionBar().setDisplayShowTitleEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().show();
showLoginFragment();
}
public void showLoginFragment()
{
final FragmentTransaction t = this.getSupportFragmentManager().beginTransaction();
currentFragment = MyFragment.newInstance();
t.replace(R.id.layoutRoot, currentFragment);
t.commit();
}
布局single_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/layoutRoot"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
类MyFragment
public class MyFragment extends RoboFragment
{
// I'm using roboguice
@InjectView(R.id.myButton) private ProgressButton myButton;
public static MyFragment newInstance()
{
Bundle arguments = new Bundle();
// no arguments for now, this comes later
MyFragment fragment = new MyFragment();
fragment.setArguments(arguments);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
setRetainInstance(true);
View result = inflater.inflate(R.layout.my_fragment, container, false);
return result;
}
}
布局my_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.my.package.ProgressButton
android:id="@+id/myButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/button_caption" />
</LinearLayout>
最后是 ProgressButton
的代码/**
* A Button with an integrated progress spinner. The button can show the progress spinner while some background process
* is running to indicate it can't be clicked again.
*/
public class ProgressButton extends RelativeLayout
{
/** The view holding the button text */
private TextView textView = null;
/** The progress spinner */
private ProgressBar progressSpinner = null;
private boolean showingProgress = false;
public ProgressButton(Context context)
{
super(context);
textView = new TextView(context);
progressSpinner = new ProgressBar(context);
initView();
}
public ProgressButton(Context context, AttributeSet attrs)
{
super(context, attrs);
textView = new TextView(context, attrs);
progressSpinner = new ProgressBar(context, attrs);
initView();
}
public ProgressButton(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
textView = new TextView(context, attrs, defStyle);
progressSpinner = new ProgressBar(context, attrs, defStyle);
initView();
}
/**
* Initializes the view with all its properties.
*/
@SuppressWarnings("deprecation")
private void initView()
{
// remove the background attributes from progressbar and textview, because they should be transparent
if (Build.VERSION.SDK_INT >= 16)
{
textView.setBackground(null);
progressSpinner.setBackground(null);
}
else
{
textView.setBackgroundDrawable(null);
progressSpinner.setBackgroundDrawable(null);
}
}
@Override
protected void onFinishInflate()
{
super.onFinishInflate();
if (!isInEditMode())
{
progressSpinner.setVisibility(View.INVISIBLE);
}
RelativeLayout layout = new RelativeLayout(getContext());
layout.setId(R.id.progressButtonContainer);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
this.addView(layout, params);
params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_LEFT);
params.leftMargin = 10;
progressSpinner.setClickable(false);
progressSpinner.setId(R.id.progressButtonProgress);
layout.addView(progressSpinner, params);
params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
textView.setClickable(false);
textView.setId(R.id.progressButtonText);
layout.addView(textView, params);
}
/**
* Disables the button and shows the progress spinner.
*/
public void showProgress()
{
this.setEnabled(false);
progressSpinner.setVisibility(View.VISIBLE);
showingProgress = true;
}
/**
* Enables the button and hides the progress spinner.
*/
public void hideProgress()
{
this.setEnabled(true);
progressSpinner.setVisibility(View.INVISIBLE);
showingProgress = false;
}
@Override
public Parcelable onSaveInstanceState()
{
Parcelable superState = super.onSaveInstanceState();
return new SavedState(superState, showingProgress);
}
@Override
public void onRestoreInstanceState(Parcelable state)
{
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
showingProgress = savedState.showProgress;
if(showingProgress)
{
showProgress();
}
else
{
hideProgress();
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected void dispatchSaveInstanceState(SparseArray container)
{
super.dispatchFreezeSelfOnly(container);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected void dispatchRestoreInstanceState(SparseArray container)
{
super.dispatchThawSelfOnly(container);
}
static class SavedState extends BaseSavedState
{
boolean showProgress = false;
SavedState(Parcelable superState, boolean showProgress)
{
super(superState);
this.showProgress = showProgress;
}
private SavedState(Parcel in)
{
super(in);
this.showProgress = in.readByte() == 0 ? false : true;
}
@Override
public void writeToParcel(Parcel out, int flags)
{
super.writeToParcel(out, flags);
out.writeByte((byte) (showProgress ? 1 : 0));
}
// required field that makes Parcelables from a Parcel
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>()
{
public SavedState createFromParcel(Parcel in)
{
return new SavedState(in);
}
public SavedState[] newArray(int size)
{
return new SavedState[size];
}
};
}
}
最佳答案
在 Daniel Bo 的有益评论之后,我很容易找到解决方案。无论是否存在保存状态, fragment 都会添加到 Activity 中。这会导致在其初始状态添加 View #3。在以下 if
循环中的 Activities onCreate
方法中包装 showLoginFragment();
可解决问题。
if(savedInstanceState == null)
{
showLoginFragment();
}
关于Android 自定义 View 在方向更改时重新创建两次,第二次没有 onRestoreInstanceState,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18873204/
所以我对 onSaveInstanceState 和 onRestoreInstanceState 有一个奇怪的问题。以下是我到目前为止所拥有的,并且运行良好。方法正常调用,值保存和恢复都很好。 @O
我需要你的帮助。我正在制作一个应用程序,我使用方法 onSaveInstanceState() 和 onRestoreInstanceState(),但第二种方法不起作用。 当按下主页按钮时,我可以看
继续上一个问题 第一个屏幕 Activity 我正在单击一个按钮并执行此操作 Intent intent = new Intent(MainMenu.this, NewClass.class); in
我最近在使用 onSaveInstanceState() 和 onRestoreInstanceState() 时遇到了一些麻烦。我有多个 Activity 使用这些方法来保存状态,以防它们被系统清理
这个问题在这里已经有了答案: onSaveInstanceState () and onRestoreInstanceState () (13 个答案) 关闭 9 年前。 我对 Android 中的
我已经编写了所有需要的代码来保存我的 Activity 状态(一个带有 EditText 小部件的简单表单)并在手机旋转时恢复它,而且效果很好。 我的问题是管理屏幕开/关变化:关闭时,onSaveIn
我想在 App 进入 onPause 时保存 textView 的值。所以我实现了 onSaveInstanceState 和 onRestoreInstanceState。但如下面的 logcat
对不起,我的不理解,但我是android开发的新手。 我有一个包含 Activity A 和 Activity B 的应用程序,我从 Activity A 转到 Activity B。当我离开 Act
我是否遗漏了什么或 Fragment 没有 onRestoreInstanceState() 方法?如果没有,我该如何获得类似的东西? 最佳答案 fragment 没有 onRestoreInstan
当我在 listView 中输入某些内容并旋转它后,listView 返回 null 而不是我输入的文本。您能解释一下为什么会发生这种情况吗? override fun onRestoreInstan
情况是我想创建一个应用程序,每次单击按钮时它应该能够在 LinearLayout 中创建一个新的 TextView。来自EditText的文本被分配给所述TextView。我成功地做到了这一点。然而,
我对 Android 开发和 StackOverflow 都很陌生,我希望我问的不是一个愚蠢的问题,这个问题以前有人问过,但我在上面找不到任何东西。 我正在制作一个应用程序,它在连接到蓝牙设备时启动(
如何保存/恢复附加到 CursorAdapter 的 ListView 的状态?示例: 我有一个带有 3 个 ListView 的 Android Activity:国家、地区、城市。 它们附加到 3
我在一个计数程序中遇到了一个问题,该程序显示了诸如 onCreate、onStart 等方法被调用了多少次,当我从 Activity1 转到 Activity2 然后再回到 Activity1 时它似
我正在开发一个应用程序,当您转到屏幕时,您可以从 onCreate 中创建的对话框中选择您的位置。选择位置后,它会将其写入预定义的 TextView。我遇到的一个问题是,当屏幕方向发生变化时,它会重新
下面的 SwiperActivity,从 ActionBarSherlock 4.0.2 库扩展 SherlockFragmentActivity。我只能在加载不同的应用程序负载,然后切换回来后,在
ClassCastException随机出现,用于在onRestoreInstanceState()中恢复Vector。恢复vector一般都很好完成,但有时会出现异常。 我认为当 Activity
在我的应用程序中,在正常操作期间执行 onRestoreInstanceStatance 函数并在某些监听器中导致空指针异常,而无需调用该监听器。我的应用程序包含大量数据,我在 onPause 中写入
我正在尝试弄清楚 onSaveInstanceState/onRestoreInstanceState 如何与对话框一起工作。使用 Acitivity 很容易,因为它们会在 Activity 被终止/
我正在尝试在我的 Activity 中保存数据而不是恢复它。我将数据保存在 onSaveInstanceState() 中,然后尝试恢复 onRestoreInstanceState() 中的数据。
我是一名优秀的程序员,十分优秀!