Android组件:Fragment切换后保存状态

时间:2022-06-28 05:48:59 其他范文 收藏本文 下载本文

Android组件:Fragment切换后保存状态(精选2篇)由网友“天天幽雅”投稿提供,下面是小编收集整理的Android组件:Fragment切换后保存状态,供大家参考借鉴,欢迎大家分享。

Android组件:Fragment切换后保存状态

篇1:Android组件:Fragment切换后保存状态

之前写的第一篇Fragment实例,和大多数人一开始学的一样,都是通过FragmentTransaction的replace方法来实现,replace方法相当于先移除remove原来所有已存在的fragments,然后添加add()当前这个fragment,这就导致了一个问题,我们切换一次,然后再切换回来,相当于重新加载了这个fragment,原来的状态不复存在,这显然与我们的日常使用不符。想要保存切换后的状态,思路还是很简单的,我们先添加了若干fragments,切换后将所有fragments都隐藏hide(),并显示show()切换后的fragment即可。

实例:山寨微信

由于代码较长,这里只讲核心的部分,有兴趣的可以下载源码来看一下

public class MainActivity extends ActionBarActivity implements OnClickListener { private View weixinLayout, tongxunluLayout, faxianLayout, woLayout; private TextView weixinTv, tongxunluTv, faxianTv, woTv; private ImageView weixinIv, tongxunluIv, faxianIv, woIv; private Fragment1 fragment1; private Fragment2 fragment2; private Fragment3 fragment3; private Fragment4 fragment4; private FragmentManager fm; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化 initViews(); fm = getFragmentManager(); // 初识状态是显示微信 weixinIv.setBackgroundResource(R.drawable.weixin2); weixinTv.setTextColor(getResources().getColor(R.color.green)); showFragment(1); } void initViews() { // 注册各IamgeView weixinIv = (ImageView) findViewById(R.id.weixin_iv); tongxunluIv = (ImageView) findViewById(R.id.tongxunlu_iv); faxianIv = (ImageView) findViewById(R.id.faxian_iv); woIv = (ImageView) findViewById(R.id.wo_iv); // 注册各TextView weixinTv = (TextView) findViewById(R.id.weixin_tv); tongxunluTv = (TextView) findViewById(R.id.tongxunlu_tv); faxianTv = (TextView) findViewById(R.id.faxian_tv); woTv = (TextView) findViewById(R.id.wo_tv); // 注册各Layout weixinLayout = (View) findViewById(R.id.weixin_layout); tongxunluLayout = (View) findViewById(R.id.tongxunlu_layout); faxianLayout = (View) findViewById(R.id.faxian_layout); woLayout = (View) findViewById(R.id.wo_layout); // 各Layout注册 weixinLayout.setOnClickListener(this); tongxunluLayout.setOnClickListener(this); faxianLayout.setOnClickListener(this); woLayout.setOnClickListener(this); } @Override public void onClick(View arg0) { // TODO Auto-generated method stub // 当点击某个layout时,先清除状态,这里的状态指的是布局里面的图片和文字 clearState(); switch (arg0.getId()) { case R.id.weixin_layout: // 如果点的是微信,将微信布局的图片和文字的颜色变为绿色 weixinIv.setBackgroundResource(R.drawable.weixin2); weixinTv.setTextColor(getResources().getColor(R.color.green)); // 显示微信的fragment showFragment(1); break; case R.id.tongxunlu_layout: tongxunluIv.setBackgroundResource(R.drawable.tongxunlu2); tongxunluTv.setTextColor(getResources().getColor(R.color.green)); showFragment(2); break; case R.id.faxian_layout: faxianIv.setBackgroundResource(R.drawable.faxian2); faxianTv.setTextColor(getResources().getColor(R.color.green)); showFragment(3); break; case R.id.wo_layout: woIv.setBackgroundResource(R.drawable.wo2); woTv.setTextColor(getResources().getColor(R.color.green)); showFragment(4); break; } } public void clearState() { // 未选中时的图片 weixinIv.setBackgroundResource(R.drawable.weixin1); tongxunluIv.setBackgroundResource(R.drawable.tongxunlu1); faxianIv.setBackgroundResource(R.drawable.faxian1); woIv.setBackgroundResource(R.drawable.wo1); // 未选中时字体颜色 weixinTv.setTextColor(getResources().getColor(R.color.black)); tongxunluTv.setTextColor(getResources().getColor(R.color.black)); faxianTv.setTextColor(getResources().getColor(R.color.black)); woTv.setTextColor(getResources().getColor(R.color.black)); } public void showFragment(int index) { FragmentTransaction ft = fm.beginTransaction(); // 想要显示一个fragment,先隐藏所有fragment,防止重叠 hideFragments(ft); switch (index) { case 1: // 如果fragment1已经存在则将其显示出来 if (fragment1 != null) ft.show(fragment1); // 否则是第一次切换则添加fragment1,注意添加后是会显示出来的,replace方法也是先remove后add else { fragment1 = new Fragment1(); ft.add(R.id.content, fragment1); } break; case 2: if (fragment2 != null) ft.show(fragment2); else { fragment2 = new Fragment2(); ft.add(R.id.content, fragment2); } break; case 3: if (fragment3 != null) ft.show(fragment3); else { fragment3 = new Fragment3(); ft.add(R.id.content, fragment3); } break; case 4: if (fragment4 != null) ft.show(fragment4); else { fragment4 = new Fragment4(); ft.add(R.id.content, fragment4); } break; } ft.commit(); } // 当fragment已被实例化,就隐藏起来 public void hideFragments(FragmentTransaction ft) { if (fragment1 != null) ft.hide(fragment1); if (fragment2 != null) ft.hide(fragment2); if (fragment3 != null) ft.hide(fragment3); if (fragment4 != null) ft.hide(fragment4); }}

当我们一开始把微信fragment的ListView下拉到如上图时,切换到通讯录fragment,然后再切换回去微信fragment,此时微信的ListView还是原来的状态,这是因为并非重新加载微信fragment,而是将其先hide起来,切换回来后再show出来,

引用上篇文章的fragment生命周期图:

如果是repalce方法,我们切换至当前fragment则进行红线以上的生命周期,切换到其他fragment后进行红线以下的生命周期。但是,如果我们使用hide()和show()的方法,切换至当前fragment依然进行红线以上的生命周期,切换到其他fragment后并没有进行其他生命周期,只是简单地隐藏了起来。这样应该很明了了吧。

源码:

download.csdn.net/detail/leelit/8179147

篇2:Android重写FragmentTabHost来实现状态保存

最近要做一个类似QQ底部有气泡的功能,试了几个方案不太好,我想很多开发者使用TabHost都会知道它不保存状态,每次都要重新加载布局,为了保存状态,使用RadioGroup来实现,状态是可以保存了,问题是无法实现气泡功能,不能自定义布局,因为RadioGroup里面只能包含RadioButton,不然状态切换不起用作,这个可以查看RadioGroup源码,为了既能保存状态又能实现气泡功能,所以只能自己修改控件了或者自己写一个类似的切换功能,查看了FragmentTabHost的源码,可以知道FragmentTabHost不保存状态是因为切换fragment的时候是使用detach和attach来Fragment的隐藏和显示的,这样的话每次切换肯定要重新加载布局,处理使用detach和attach,我们还可以使用show和hide来实现显示和隐藏,这样可以保存状态,方案出来了就是修改FragmentTabHost源码将切换Fragment的方式detach和attach改为hide和show,

下面就是修改后的FragmentTabHost的源码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

/*

* Copyright (C) 2012 The Android Open Source Project

*

* Licensed under the Apache License, Version 2.0 (the “License”);

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

*     www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an “AS IS” BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package com.jwzhangjie.com;

import java.util.ArrayList;

import android.content.Context;

import android.content.res.TypedArray;

import android.os.Bundle;

import android.os.Parcel;

import android.os.Parcelable;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentManager;

import android.support.v4.app.FragmentTransaction;

import android.util.AttributeSet;

import android.view.View;

import android.view.ViewGroup;

import android.widget.FrameLayout;

import android.widget.LinearLayout;

import android.widget.TabHost;

import android.widget.TabWidget;

/**

* Special TabHost that allows the use of {@link Fragment} objects for its tab

* content. When placing this in a view hierarchy, after inflating the hierarchy

* you must call {@link #setup(Context, FragmentManager, int)} to complete the

* initialization of the tab host.

*

*

* Here is a simple example of using a FragmentTabHost in an Activity:

*

* {@sample

* development/samples/Support4Demos/src/com/example/android/supportv4/app/

* FragmentTabs.java complete}

*

*

* This can also be used inside of a fragment through fragment nesting:

*

* {@sample

* development/samples/Support4Demos/src/com/example/android/supportv4/app/

* FragmentTabsFragmentSupport.java complete}

*/

public class FragmentTabHost extends TabHost implements

TabHost.OnTabChangeListener {

private final ArrayList mTabs = new ArrayList();

private FrameLayout mRealTabContent;

private Context mContext;

private FragmentManager mFragmentManager;

private int mContainerId;

private TabHost.OnTabChangeListener mOnTabChangeListener;

private TabInfo mLastTab;

private boolean mAttached;

static final class TabInfo {

private final String tag;

private final Class clss;

private final Bundle args;

private Fragment fragment;

TabInfo(String _tag, Class _class, Bundle _args) {

tag = _tag;

clss = _class;

args = _args;

}

}

static class DummyTabFactory implements TabHost.TabContentFactory {

private final Context mContext;

public DummyTabFactory(Context context) {

mContext = context;

}

@Override

public View createTabContent(String tag) {

View v = new View(mContext);

v.setMinimumWidth(0);

v.setMinimumHeight(0);

return v;

}

}

static class SavedState extends BaseSavedState {

String curTab;

SavedState(Parcelable superState) {

super(superState);

}

private SavedState(Parcel in) {

super(in);

curTab = in.readString();

}

@Override

public void writeToParcel(Parcel out, int flags) {

super.writeToParcel(out, flags);

out.writeString(curTab);

}

@Override

public String toString() {

return “FragmentTabHost.SavedState{”

+ Integer.toHexString(System.identityHashCode(this))

+ “ curTab=” + curTab + “}”;

}

public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {

public SavedState createFromParcel(Parcel in) {

return new SavedState(in);

}

public SavedState[] newArray(int size) {

return new SavedState[size];

}

};

}

public FragmentTabHost(Context context) {

// Note that we call through to the version that takes an AttributeSet,

// because the simple Context construct can result in a broken object!

super(context, null);

initFragmentTabHost(context, null);

}

public FragmentTabHost(Context context, AttributeSet attrs) {

super(context, attrs);

initFragmentTabHost(context, attrs);

}

private void initFragmentTabHost(Context context, AttributeSet attrs) {

TypedArray a = context.obtainStyledAttributes(attrs,

new int[] { android.R.attr.inflatedId }, 0, 0);

mContainerId = a.getResourceId(0, 0);

a.recycle();

super.setOnTabChangedListener(this);

}

private void ensureHierarchy(Context context) {

// If owner hasn't made its own view hierarchy, then as a convenience

// we will construct a standard one here.

if (findViewById(android.R.id.tabs) == null) {

LinearLayout ll = new LinearLayout(context);

ll.setOrientation(LinearLayout.VERTICAL);

addView(ll, new FrameLayout.LayoutParams(

ViewGroup.LayoutParams.MATCH_PARENT,

ViewGroup.LayoutParams.MATCH_PARENT));

TabWidget tw = new TabWidget(context);

tw.setId(android.R.id.tabs);

tw.setOrientation(TabWidget.HORIZONTAL);

ll.addView(tw, new LinearLayout.LayoutParams(

ViewGroup.LayoutParams.MATCH_PARENT,

ViewGroup.LayoutParams.WRAP_CONTENT, 0));

FrameLayout fl = new FrameLayout(context);

fl.setId(android.R.id.tabcontent);

ll.addView(fl, new LinearLayout.LayoutParams(0, 0, 0));

mRealTabContent = fl = new FrameLayout(context);

mRealTabContent.setId(mContainerId);

ll.addView(fl, new LinearLayout.LayoutParams(

LinearLayout.LayoutParams.MATCH_PARENT, 0, 1));

}

}

/**

* @deprecated Don't call the original TabHost setup, you must instead call

*            {@link #setup(Context, FragmentManager)} or

*            {@link #setup(Context, FragmentManager, int)}.

*/

@Override

@Deprecated

public void setup() {

throw new IllegalStateException(

“Must call setup() that takes a Context and FragmentManager”);

}

public void setup(Context context, FragmentManager manager) {

ensureHierarchy(context); // Ensure views required by super.setup()

super.setup();

mContext = context;

mFragmentManager = manager;

ensureContent();

}

public void setup(Context context, FragmentManager manager, int containerId) {

ensureHierarchy(context); // Ensure views required by super.setup()

super.setup();

mContext = context;

mFragmentManager = manager;

mContainerId = containerId;

ensureContent();

mRealTabContent.setId(containerId);

// We must have an ID to be able to save/restore our state. If

// the owner hasn't set one at this point, we will set it ourself.

if (getId() == View.NO_ID) {

setId(android.R.id.tabhost);

}

}

private void ensureContent() {

if (mRealTabContent == null) {

mRealTabContent = (FrameLayout) findViewById(mContainerId);

if (mRealTabContent == null) {

throw new IllegalStateException(

“No tab content FrameLayout found for id ”

+ mContainerId);

}

}

}

@Override

public void setOnTabChangedListener(OnTabChangeListener l) {

mOnTabChangeListener = l;

}

public void addTab(TabHost.TabSpec tabSpec, Class clss, Bundle args) {

tabSpec.setContent(new DummyTabFactory(mContext));

String tag = tabSpec.getTag();

TabInfo info = new TabInfo(tag, clss, args);

if (mAttached) {

// If we are already attached to the window, then check to make

// sure this tab's fragment is inactive if it exists. This shouldn't

// normally happen.

info.fragment = mFragmentManager.findFragmentByTag(tag);

if (info.fragment != null && !info.fragment.isDetached()) {

FragmentTransaction ft = mFragmentManager.beginTransaction();

//             ft.detach(info.fragment);

ft.hide(info.fragment);

ft.commit();

}

}

mTabs.add(info);

addTab(tabSpec);

}

@Override

protected void onAttachedToWindow() {

super.onAttachedToWindow();

String currentTab = getCurrentTabTag();

// Go through all tabs and make sure their fragments match

// the correct state.

FragmentTransaction ft = null;

for (int i = 0; i < mTabs.size(); i++) {

TabInfo tab = mTabs.get(i);

tab.fragment = mFragmentManager.findFragmentByTag(tab.tag);

//         if (tab.fragment != null && !tab.fragment.isDetached()) {

if (tab.fragment != null) {

if (tab.tag.equals(currentTab)) {

// The fragment for this tab is already there and

// active, and it is what we really want to have

// as the current tab. Nothing to do.

mLastTab = tab;

} else {

// This fragment was restored in the active state,

// but is not the current tab. Deactivate it.

if (ft == null) {

ft = mFragmentManager.beginTransaction();

}

//                 ft.detach(tab.fragment);

ft.hide(tab.fragment);

}

}

}

// We are now ready to go. Make sure we are switched to the

// correct tab.

mAttached = true;

ft = doTabChanged(currentTab, ft);

if (ft != null) {

ft.commit();

mFragmentManager.executePendingTransactions();

}

}

@Override

protected void onDetachedFromWindow() {

super.onDetachedFromWindow();

mAttached = false;

}

@Override

protected Parcelable onSaveInstanceState() {

Parcelable superState = super.onSaveInstanceState();

SavedState ss = new SavedState(superState);

ss.curTab = getCurrentTabTag();

return ss;

}

@Override

protected void onRestoreInstanceState(Parcelable state) {

SavedState ss = (SavedState) state;

super.onRestoreInstanceState(ss.getSuperState());

setCurrentTabByTag(ss.curTab);

}

@Override

public void onTabChanged(String tabId) {

if (mAttached) {

FragmentTransaction ft = doTabChanged(tabId, null);

if (ft != null) {

ft.commit();

}

}

if (mOnTabChangeListener != null) {

mOnTabChangeListener.onTabChanged(tabId);

}

}

private FragmentTransaction doTabChanged(String tabId,

FragmentTransaction ft) {

TabInfo newTab = null;

for (int i = 0; i < mTabs.size(); i++) {

TabInfo tab = mTabs.get(i);

if (tab.tag.equals(tabId)) {

newTab = tab;

}

}

if (newTab == null) {

throw new IllegalStateException(“No tab known for tag ” + tabId);

}

if (mLastTab != newTab) {

if (ft == null) {

ft = mFragmentManager.beginTransaction();

}

if (mLastTab != null) {

if (mLastTab.fragment != null) {

//                 ft.detach(mLastTab.fragment);

ft.hide(mLastTab.fragment);

}

}

if (newTab != null) {

if (newTab.fragment == null) {

newTab.fragment = Fragment.instantiate(mContext,

newTab.clss.getName(), newTab.args);

ft.add(mContainerId, newTab.fragment, newTab.tag);

} else {

//                 ft.attach(newTab.fragment);

ft.show(newTab.fragment);

}

}

mLastTab = newTab;

}

return ft;

}

}

安卓论文开题报告

安卓开发心得实例

安卓应用商店用户调查报告

安卓实习心得感悟

工程师实习报告

android自定义组件(手机加速球+水面波动效果)

学习android的方法

从零开始学Android应用安全测试(Part1)

安卓项目总结

Android 最火的快速开发框架AndroidAnnotations使用

Android组件:Fragment切换后保存状态
《Android组件:Fragment切换后保存状态.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

【Android组件:Fragment切换后保存状态(精选2篇)】相关文章:

软件开发实习报告2024-04-07

百度面试Android面试题2022-10-05

笔试题目22024-05-05

工程的实习报告2022-07-29

数据库基本操作的说课稿2022-05-06

全新android Tab控件PagerSlidingTabStrip最简使用方法2022-10-22

C.net web开发面试题2024-01-18

wps怎么打分数?2023-04-27

安卓的英文是什么2023-11-13

简历详述范文2022-10-13

点击下载本文文档