




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】Android怎么实现加载状态视图切换效果
这篇文章主要介绍了Android怎么实现加载状态视图切换效果,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让在下带着大家一起了解一下。关于Android加载状态视图切换,具体内容如下1.关于Android界面切换状态的介绍怎样切换界面状态?有些界面想定制自定义状态?状态如何添加点击事件?下面就为解决这些问题!内容界面加载数据中加载数据错误加载后没有数据没有网络2.思路转变,抽取分离类管理几种状态以前做法:直接把这些界面include到main界面中,然后动态去切换界面,后来发现这样处理不容易复用到其他项目中,而且在activity中处理这些状态的显示和隐藏比较乱利用子类继承父类特性,在父类中写切换状态,但有些界面如果没有继承父类,又该如何处理现在做法:让View状态的切换和Activity彻底分离开,必须把这些状态View都封装到一个管理类中,然后暴露出几个方法来实现View之间的切换。在不同的项目中可以需要的View也不一样,所以考虑把管理类设计成builder模式来自由的添加需要的状态View3.关于该状态切换工具优点分析可以自由切换内容,空数据,异常错误,加载,网络错误等5种状态父类BaseActivity直接暴露5中状态,方便子类统一管理状态切换/**
*
================================================
*
作
者:杨充
*
版
本:1.0
*
创建日期:2017/7/6
*
描
述:抽取类
*
修订历史:
*
================================================
*/
public
abstract
class
BaseActivity
extends
AppCompatActivity
{
protected
StatusLayoutManager
statusLayoutManager;
@Override
protected
void
onCreate(@Nullable
Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base_view);
initStatusLayout();
initBaseView();
initToolBar();
initView();
}
protected
abstract
void
initStatusLayout();
protected
abstract
void
initView();
/**
*
获取到布局
*/
private
void
initBaseView()
{
LinearLayout
ll_main
=
(LinearLayout)
findViewById(R.id.ll_main);
ll_main.addView(statusLayoutManager.getRootLayout());
}
//正常展示数据状态
protected
void
showContent()
{
statusLayoutManager.showContent();
}
//加载数据为空时状态
protected
void
showEmptyData()
{
statusLayoutManager.showEmptyData();
}
//加载数据错误时状态
protected
void
showError()
{
statusLayoutManager.showError();
}
//网络错误时状态
protected
void
showNetWorkError()
{
statusLayoutManager.showNetWorkError();
}
//正在加载中状态
protected
void
showLoading()
{
statusLayoutManager.showLoading();
}
}当状态是加载数据失败时,点击可以刷新数据;当状态是无网络时,点击可以设置网络/**
*
点击重新刷新
*/
private
void
initErrorDataView()
{
statusLayoutManager.showError();
LinearLayout
ll_error_data
=
(LinearLayout)
findViewById(R.id.ll_error_data);
ll_error_data.setOnClickListener(new
View.OnClickListener()
{
@Override
public
void
onClick(View
view)
{
initData();
adapter.notifyDataSetChanged();
showContent();
}
});
}
/**
*
点击设置网络
*/
private
void
initSettingNetwork()
{
statusLayoutManager.showNetWorkError();
LinearLayout
ll_set_network
=
(LinearLayout)
findViewById(R.id.ll_set_network);
ll_set_network.setOnClickListener(new
View.OnClickListener()
{
@Override
public
void
onClick(View
view)
{
Intent
intent
=
new
Intent("android.settings.WIRELESS_SETTINGS");
startActivity(intent);
}
});
}倘若有些页面想定制状态布局,也可以自由实现,很简单:/**
*
自定义加载数据为空时的状态布局
*/
private
void
initEmptyDataView()
{
statusLayoutManager.showEmptyData();
//此处是自己定义的状态布局
**statusLayoutManager.showLayoutEmptyData(R.layout.activity_emptydata);**
LinearLayout
ll_empty_data
=
(LinearLayout)
findViewById(R.id.ll_empty_data);
ll_empty_data.setOnClickListener(new
View.OnClickListener()
{
@Override
public
void
onClick(View
view)
{
initData();
adapter.notifyDataSetChanged();
showContent();
}
});
}4.如何实现的步骤1).先看看状态管理器类【builder建造者模式】loadingLayoutResId和contentLayoutResId代表等待加载和显示内容的xml文件几种异常状态要用ViewStub,因为在界面状态切换中loading和内容View都是一直需要加载显示的,但是其他的3个只有在没数据或者网络异常的情况下才会加载显示,所以用ViewStub来加载他们可以提高性能。public
class
StateLayoutManager
{
final
Context
context;
final
ViewStub
netWorkErrorVs;
final
int
netWorkErrorRetryViewId;
final
ViewStub
emptyDataVs;
final
int
emptyDataRetryViewId;
final
ViewStub
errorVs;
final
int
errorRetryViewId;
final
int
loadingLayoutResId;
final
int
contentLayoutResId;
final
int
retryViewId;
final
int
emptyDataIconImageId;
final
int
emptyDataTextTipId;
final
int
errorIconImageId;
final
int
errorTextTipId;
final
VLayout
errorLayout;
final
VLayout
emptyDataLayout;
final
RootFrameLayout
rootFrameLayout;
final
OnShowHideViewListener
onShowHideViewListener;
final
OnRetryListener
onRetryListener;
public
StateLayoutManager(Builder
builder)
{
this.context
=
builder.context;
this.loadingLayoutResId
=
builder.loadingLayoutResId;
WorkErrorVs
=
WorkErrorVs;
WorkErrorRetryViewId
=
WorkErrorRetryViewId;
this.emptyDataVs
=
builder.emptyDataVs;
this.emptyDataRetryViewId
=
builder.emptyDataRetryViewId;
this.errorVs
=
builder.errorVs;
this.errorRetryViewId
=
builder.errorRetryViewId;
this.contentLayoutResId
=
builder.contentLayoutResId;
this.onShowHideViewListener
=
builder.onShowHideViewListener;
this.retryViewId
=
builder.retryViewId;
this.onRetryListener
=
builder.onRetryListener;
this.emptyDataIconImageId
=
builder.emptyDataIconImageId;
this.emptyDataTextTipId
=
builder.emptyDataTextTipId;
this.errorIconImageId
=
builder.errorIconImageId;
this.errorTextTipId
=
builder.errorTextTipId;
this.errorLayout
=
builder.errorLayout;
this.emptyDataLayout
=
builder.emptyDataLayout;
rootFrameLayout
=
new
RootFrameLayout(this.context);
ViewGroup.LayoutParams
layoutParams
=
new
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
rootFrameLayout.setLayoutParams(layoutParams);
rootFrameLayout.setStatusLayoutManager(this);
}
/**
*
显示loading
*/
public
void
showLoading()
{
rootFrameLayout.showLoading();
}
/**
*
显示内容
*/
public
void
showContent()
{
rootFrameLayout.showContent();
}
/**
*
显示空数据
*/
public
void
showEmptyData(int
iconImage,
String
textTip)
{
rootFrameLayout.showEmptyData(iconImage,
textTip);
}
/**
*
显示空数据
*/
public
void
showEmptyData()
{
showEmptyData(0,
"");
}
/**
*
显示空数据
*/
public
void
showLayoutEmptyData(Object...
objects)
{
rootFrameLayout.showLayoutEmptyData(objects);
}
/**
*
显示网络异常
*/
public
void
showNetWorkError()
{
rootFrameLayout.showNetWorkError();
}
/**
*
显示异常
*/
public
void
showError(int
iconImage,
String
textTip)
{
rootFrameLayout.showError(iconImage,
textTip);
}
/**
*
显示异常
*/
public
void
showError()
{
showError(0,
"");
}
public
void
showLayoutError(Object...
objects)
{
rootFrameLayout.showLayoutError(objects);
}
/**
*
得到root
布局
*/
public
View
getRootLayout()
{
return
rootFrameLayout;
}
public
static
final
class
Builder
{
private
Context
context;
private
int
loadingLayoutResId;
private
int
contentLayoutResId;
private
ViewStub
netWorkErrorVs;
private
int
netWorkErrorRetryViewId;
private
ViewStub
emptyDataVs;
private
int
emptyDataRetryViewId;
private
ViewStub
errorVs;
private
int
errorRetryViewId;
private
int
retryViewId;
private
int
emptyDataIconImageId;
private
int
emptyDataTextTipId;
private
int
errorIconImageId;
private
int
errorTextTipId;
private
VLayout
errorLayout;
private
VLayout
emptyDataLayout;
private
OnShowHideViewListener
onShowHideViewListener;
private
OnRetryListener
onRetryListener;
public
Builder(Context
context)
{
this.context
=
context;
}
/**
*
自定义加载布局
*/
public
Builder
loadingView(@LayoutRes
int
loadingLayoutResId)
{
this.loadingLayoutResId
=
loadingLayoutResId;
return
this;
}
/**
*
自定义网络错误布局
*/
public
Builder
netWorkErrorView(@LayoutRes
int
newWorkErrorId)
{
netWorkErrorVs
=
new
ViewStub(context);
netWorkErrorVs.setLayoutResource(newWorkErrorId);
return
this;
}
/**
*
自定义加载空数据布局
*/
public
Builder
emptyDataView(@LayoutRes
int
noDataViewId)
{
emptyDataVs
=
new
ViewStub(context);
emptyDataVs.setLayoutResource(noDataViewId);
return
this;
}
/**
*
自定义加载错误布局
*/
public
Builder
errorView(@LayoutRes
int
errorViewId)
{
errorVs
=
new
ViewStub(context);
errorVs.setLayoutResource(errorViewId);
return
this;
}
/**
*
自定义加载内容正常布局
*/
public
Builder
contentView(@LayoutRes
int
contentLayoutResId)
{
this.contentLayoutResId
=
contentLayoutResId;
return
this;
}
public
Builder
errorLayout(VLayout
errorLayout)
{
this.errorLayout
=
errorLayout;
this.errorVs
=
errorLayout.getLayoutVs();
return
this;
}
public
Builder
emptyDataLayout(VLayout
emptyDataLayout)
{
this.emptyDataLayout
=
emptyDataLayout;
this.emptyDataVs
=
emptyDataLayout.getLayoutVs();
return
this;
}
public
Builder
netWorkErrorRetryViewId(int
netWorkErrorRetryViewId)
{
WorkErrorRetryViewId
=
netWorkErrorRetryViewId;
return
this;
}
public
Builder
emptyDataRetryViewId(int
emptyDataRetryViewId)
{
this.emptyDataRetryViewId
=
emptyDataRetryViewId;
return
this;
}
public
Builder
errorRetryViewId(int
errorRetryViewId)
{
this.errorRetryViewId
=
errorRetryViewId;
return
this;
}
public
Builder
retryViewId(int
retryViewId)
{
this.retryViewId
=
retryViewId;
return
this;
}
public
Builder
emptyDataIconImageId(int
emptyDataIconImageId)
{
this.emptyDataIconImageId
=
emptyDataIconImageId;
return
this;
}
public
Builder
emptyDataTextTipId(int
emptyDataTextTipId)
{
this.emptyDataTextTipId
=
emptyDataTextTipId;
return
this;
}
public
Builder
errorIconImageId(int
errorIconImageId)
{
this.errorIconImageId
=
errorIconImageId;
return
this;
}
public
Builder
errorTextTipId(int
errorTextTipId)
{
this.errorTextTipId
=
errorTextTipId;
return
this;
}
public
Builder
onShowHideViewListener(OnShowHideViewListener
onShowHideViewListener)
{
this.onShowHideViewListener
=
onShowHideViewListener;
return
this;
}
public
Builder
onRetryListener(OnRetryListener
onRetryListener)
{
this.onRetryListener
=
onRetryListener;
return
this;
}
public
StateLayoutManager
build()
{
return
new
StateLayoutManager(this);
}
}
public
static
Builder
newBuilder(Context
context)
{
return
new
Builder(context);
}
}2).大约5种状态,如何管理这些状态?添加到集合中,Android中选用SparseArray比HashMap更省内存,在某些条件下性能更好,主要是因为它避免了对key的自动装箱(int转为Integer类型),它内部则是通过两个数组来进行数据存储的,一个存储key,另外一个存储value,为了优化性能,它内部对数据还采取了压缩的方式来表示稀疏数组的数据,从而节约内存空间/**存放布局集合
*/
private
SparseArray<View>
layoutSparseArray
=
new
SparseArray();/**将布局添加到集合
*/
……
private
void
addLayoutResId(@LayoutRes
int
layoutResId,
int
id)
{
View
resView
=
LayoutInflater.from(mStatusLayoutManager.context).inflate(layoutResId,
null);
**layoutSparseArray.put(id,
resView);**
addView(resView);
}3).当显示某个布局时,调用的方法如下方法里面通过id判断来执行不同的代码,首先判断ViewStub是否为空,如果为空就代表没有添加这个View就返回false,不为空就加载View并且添加到集合当中,然后调用showHideViewById方法显示隐藏View,retryLoad方法是给重试按钮添加事件/**
*
显示loading
*/
public
void
showLoading()
{
if
(layoutSparseArray.get(LAYOUT_LOADING_ID)
!=
null)
**showHideViewById**(LAYOUT_LOADING_ID);
}
/**
*
显示内容
*/
public
void
showContent()
{
if
(layoutSparseArray.get(LAYOUT_CONTENT_ID)
!=
null)
**showHideViewById**(LAYOUT_CONTENT_ID);
}
/**
*
显示空数据
*/
public
void
showEmptyData(int
iconImage,
String
textTip)
{
if
(**inflateLayout**(LAYOUT_EMPTYDATA_ID))
{
showHideViewById(LAYOUT_EMPTYDATA_ID);
emptyDataViewAddData(iconImage,
textTip);
}
}
/**
*
显示网络异常
*/
public
void
showNetWorkError()
{
if
(**inflateLayout**(LAYOUT_NETWORK_ERROR_ID))
showHideViewById(LAYOUT_NETWORK_ERROR_ID);
}
/**
*
显示异常
*/
public
void
showError(int
iconImage,
String
textTip)
{
if
(**inflateLayout**(LAYOUT_ERROR_ID))
{
showHideViewById(LAYOUT_ERROR_ID);
errorViewAddData(iconImage,
textTip);
}
}
//调用inflateLayout方法,方法返回true然后调用showHideViewById方法
private
boolean
inflateLayout(int
id)
{
boolean
isShow
=
true;
if
(layoutSparseArray.get(id)
!=
null)
return
isShow;
switch
(id)
{
case
LAYOUT_NETWORK_ERROR_ID:
if
(mStatusLayoutMWorkErrorVs
!=
null)
{
View
view
=
mStatusLayoutMWorkErrorVs.inflate();
retryLoad(view,
mStatusLayoutMWorkErrorRetryViewId);
layoutSparseArray.put(id,
view);
isShow
=
true;
}
else
{
isShow
=
false;
}
break;
case
LAYOUT_ERROR_ID:
if
(mStatusLayoutManager.errorVs
!=
null)
{
View
view
=
mStatusLayoutManager.errorVs.inflate();
if
(mStatusLayoutManager.errorLayout
!=
null)
mStatusLayoutManager.errorLayout.setView(view);
retryLoad(view,
mStatusLayoutManager.errorRetryViewId);
layoutSparseArray.put(id,
view);
isShow
=
true;
}
else
{
isShow
=
false;
}
break;
case
LAYOUT_EMPTYDATA_ID:
if
(mStatusLayoutManager.emptyDataVs
!=
null)
{
View
view
=
mStatusLayoutManager.emptyDataVs.inflate();
if
(mStatusLayoutManager.emptyDataLayout
!=
null)
mStatusLayoutManager.emptyDataLayout.setView(view);
retryLoad(view,
mStatusLayoutManager.emptyDataRetryViewId);
layoutSparseArray.put(id,
view);
isShow
=
true;
}
else
{
isShow
=
false;
}
break;
}
return
isShow;
}4).然后在根据id隐藏布局通过id找到需要显示的View并且显示它,隐藏其他View,如果显示隐藏监听事件不为空,就分别调用它的显示和隐藏方法/**
*
根据ID显示隐藏布局
*
@param
id
*/
private
void
showHideViewById(int
id)
{
for
(int
i
=
0;
i
<
layoutSparseArray.size();
i++)
{
int
key
=
layoutSparseArray.keyAt(i);
View
valueView
=
layoutSparseArray.valueAt(i);
//显示该view
if(key
==
id)
{
valueView.setVisibility(View.VISIBLE);
if(mStatusLayoutManager.onShowHideViewListener
!=
null)
mStatusLayoutManager.onShowHideViewListener.onShowView(valueView,
key);
}
else
{
if(valueView.getVisibility()
!=
View.GONE)
{
valueView.setVisibility(View.GONE);
if(mStatusLayoutManager.onShowHideViewListener
!=
null)
mStatusLayoutManager.onShowHideViewListener.onHideView(valueView,
key);
}
}
}
}5).最后看看重新加载方法/**
*
重试加载
*/
private
void
retryLoad(View
view,
int
id)
{
View
retryView
=
view.findViewById(mStatusLayoutManager.retryViewId
!=
0
?
mStatu
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 公共交通工具安全防护方案计划
- 生物观察实践活动方案计划
- 仓库作业效率提升的案例分析计划
- 肺癌合并肺栓塞护理
- 未来市场的年度工作应对策略计划
- 《贵州万胜恒通矿业有限责任公司习水县温水镇吉华煤矿(变更)矿产资源绿色开发利用方案(三合一)》评审意见
- 木林森品牌新形象
- Definitiontheability(英文版知识讲义)
- 储能锂电池知识培训课件
- 内蒙古开鲁县高中生物 第四章 细胞的物质输入和输出 4.1 物质跨膜运输的实例 第一课时教学实录 新人教版必修1
- 四年级下册英语课件:Unit 4 There are seven days in a week-Lesson 19人教精通版
- DB63-T 2033-2022 青海省农房建筑节能建设标准
- 《桥梁工程计算书》word版
- 中华人民共和国特种设备安全法(节选)
- 篮球比赛计分表
- 施工现场安全隐患检查(附标准规范)
- 吞咽障碍及吞咽功能的评定
- 拱涵计算书-6.0m-1m
- 高中有机化学必修模块与选修模块的衔接
- BBC美丽中国英文字幕
- 《自然保护区综合科学考察规程》
评论
0/150
提交评论