#Day04 #
#分类模块 ##
网络数据加载
对象封装
public class CategoryInfo {
public String name1;
public String name2;
public String name3;
public String url1;
public String url2;
public String url3;
public String title;
public boolean isTitle;// 表示当前对象是否是标题
}
CategoryProtocol
/**
-
分类页访问网络
* -
@author Kevin
*
*/
public class CategoryProtocol extends BaseProtocol<ArrayList> {@Override public String getKey() { return "category"; } @Override public String getParams() { return ""; } @Override public ArrayList<CategoryInfo> parseJson(String result) { try { JSONArray ja = new JSONArray(result); ArrayList<CategoryInfo> list = new ArrayList<CategoryInfo>(); for (int i = 0; i < ja.length(); i++) { CategoryInfo titleInfo = new CategoryInfo(); JSONObject jo = (JSONObject) ja.get(i); // 添加标题对象 if (jo.has("title")) { String title = jo.getString("title"); titleInfo.isTitle = true; titleInfo.title = title; list.add(titleInfo); } if (jo.has("infos")) { JSONArray array = jo.getJSONArray("infos"); for (int j = 0; j < array.length(); j++) { CategoryInfo info = new CategoryInfo(); JSONObject obj = array.getJSONObject(j); info.name1 = obj.getString("name1"); info.name2 = obj.getString("name2"); info.name3 = obj.getString("name3"); info.url1 = obj.getString("url1"); info.url2 = obj.getString("url2"); info.url3 = obj.getString("url3"); info.isTitle = false; list.add(info); } } } return list; } catch (Exception e) { e.printStackTrace(); } return null; } }
CategoryFragment
/**
-
分类
* -
@author Kevin
*
*/
public class CategoryFragment extends BaseFragment {private ArrayList<CategoryInfo> mList; @Override public View onCreateSuccessView() { MyListView view = new MyListView(UIUtils.getContext()); view.setAdapter(new CategoryAdapter(mList)); return view; } @Override public ResultState onLoad() { CategoryProtocol protocol = new CategoryProtocol(); mList = protocol.getData(0); return check(mList); } class CategoryAdapter extends MyBaseAdapter<CategoryInfo> { public CategoryAdapter(ArrayList<CategoryInfo> list) { super(list); } // 根据当前位置,返回相应的Holder对象 @Override public BaseHolder<CategoryInfo> getHolder(int position) { CategoryInfo info = getItem(position); if (info.isTitle) { return new TitleHolder();// 标题栏holder } return new CategoryHolder();// 普通类型holer } @Override public ArrayList<CategoryInfo> onLoadMore() { return null; } @Override public boolean hasMore() { return false;// 没有更多数据, 无需加载下一页 } @Override public int getViewTypeCount() { return super.getViewTypeCount() + 1;// 在原来基础上,新增标题栏类型 } // 根据位置判断当前item的类型 @Override public int getInnerType(int position) { CategoryInfo info = getItem(position); if (info.isTitle) {// 标题栏类型 return super.getInnerType(position) + 1; } else {// 普通类型 return super.getInnerType(position); } } } }
Holder
/**
-
分类页标题栏holder
*/
public class TitleHolder extends BaseHolder {private TextView tvTitle; @Override public View initView() { View view = View.inflate(UIUtils.getContext(), R.layout.list_item_title, null); tvTitle = (TextView) view.findViewById(R.id.tv_title); return view; } @Override public void refreshView(CategoryInfo data) { tvTitle.setText(data.title); } } --------------------------------------------- list_item_title.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#000" android:textSize="18sp" /> </LinearLayout> -------------------------------------------------- /**
-
分类holder
* -
@author Kevin
*/
public class CategoryHolder extends BaseHolder implements
OnClickListener {private ImageView ivIcon1, ivIcon2, ivIcon3; private TextView tvName1, tvName2, tvName3; private LinearLayout llGrid1, llGrid2, llGrid3; private BitmapUtils mBitmapUtils; @Override public View initView() { View view = View.inflate(UIUtils.getContext(), R.layout.list_item_category, null); mBitmapUtils = BitmapHelper.getBitmapUtils(); mBitmapUtils.configDefaultLoadingImage(R.drawable.ic_default); ivIcon1 = (ImageView) view.findViewById(R.id.iv_icon1); ivIcon2 = (ImageView) view.findViewById(R.id.iv_icon2); ivIcon3 = (ImageView) view.findViewById(R.id.iv_icon3); tvName1 = (TextView) view.findViewById(R.id.tv_name1); tvName2 = (TextView) view.findViewById(R.id.tv_name2); tvName3 = (TextView) view.findViewById(R.id.tv_name3); llGrid1 = (LinearLayout) view.findViewById(R.id.ll_grid1); llGrid2 = (LinearLayout) view.findViewById(R.id.ll_grid2); llGrid3 = (LinearLayout) view.findViewById(R.id.ll_grid3); llGrid1.setOnClickListener(this); llGrid2.setOnClickListener(this); llGrid3.setOnClickListener(this); return view; } @Override public void refreshView(CategoryInfo data) { if (data != null) { tvName1.setText(data.name1); tvName2.setText(data.name2); tvName3.setText(data.name3); mBitmapUtils.display(ivIcon1, HttpHelper.URL + "image?name="
data.url1);
mBitmapUtils.display(ivIcon2, HttpHelper.URL + “image?name=”
data.url2);
mBitmapUtils.display(ivIcon3, HttpHelper.URL + “image?name=”
data.url3);
}
}
@Override
public void onClick(View v) {
CategoryInfo data = getData();
switch (v.getId()) {
case R.id.ll_grid1:
Toast.makeText(UIUtils.getContext(), data.name1, Toast.LENGTH_SHORT)
.show();
break;
case R.id.ll_grid2:
Toast.makeText(UIUtils.getContext(), data.name2, Toast.LENGTH_SHORT)
.show();
break;
case R.id.ll_grid3:
Toast.makeText(UIUtils.getContext(), data.name3, Toast.LENGTH_SHORT)
.show();
break;
default:
break;
}
}
}
--------------------------------------------
list_item_category.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/ll_grid1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/grid_item_bg_selector"
android:gravity="center"
android:orientation="vertical"
android:padding="5dp" >
<ImageView
android:id="@+id/iv_icon1"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/ic_default" />
<TextView
android:id="@+id/tv_name1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="休闲"
android:textColor="#000"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_grid2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/grid_item_bg_selector"
android:gravity="center"
android:orientation="vertical"
android:padding="5dp" >
<ImageView
android:id="@+id/iv_icon2"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/ic_default" />
<TextView
android:id="@+id/tv_name2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="休闲"
android:textColor="#000"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_grid3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/grid_item_bg_selector"
android:gravity="center"
android:orientation="vertical"
android:padding="5dp" >
<ImageView
android:id="@+id/iv_icon3"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/ic_default" />
<TextView
android:id="@+id/tv_name3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="休闲"
android:textColor="#000"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
首页轮播图模块 ##
HomeFragment
@Override
public View onCreateSuccessView() {
MyListView view = new MyListView(UIUtils.getContext());
// 添加头布局
HomeHeaderHolder header = new HomeHeaderHolder();
view.addHeaderView(header.getRootView());
// 设置头布局数据
header.setData(mPicList);
view.setAdapter(new HomeAdapter(mList));
return view;
}
@Override
public ResultState onLoad() {
// 从网络加载数据
HomeProtocol protocol = new HomeProtocol();
mList = protocol.getData(0);// 加载第一页数据
mPicList = protocol.getPicList();
return check(mList);
}
HomeHeaderHolder
public class HomeHeaderHolder extends BaseHolder<ArrayList<String>> {
private ArrayList<String> mList;
private ViewPager mViewPager;
private LinearLayout mIndicator;
private int mPreviousPos;// 上一个被选中圆点的位置
@Override
public View initView() {
// 头布局的根布局
RelativeLayout header = new RelativeLayout(UIUtils.getContext());
// 根布局布局参数
AbsListView.LayoutParams params = new AbsListView.LayoutParams(
AbsListView.LayoutParams.MATCH_PARENT,
UIUtils.getDimen(R.dimen.list_header_height));
header.setLayoutParams(params);
// 初始化ViewPager
mViewPager = new ViewPager(UIUtils.getContext());
mViewPager.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT));
// 将ViewPager添加给根布局
header.addView(mViewPager);
// 页码指示器
mIndicator = new LinearLayout(UIUtils.getContext());
// 设置边距
int padding = UIUtils.dip2px(5);
mIndicator.setPadding(padding, padding, padding, padding);
// 初始化页码指示器布局参数
RelativeLayout.LayoutParams iParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
// 设置当前线性布局相对于父控件的位置
iParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
iParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
mIndicator.setLayoutParams(iParams);
// 将页码指示器添加给根布局
header.addView(mIndicator);
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
// 将当前圆点设置为选中样式
ImageView view = (ImageView) mIndicator.getChildAt(arg0);
view.setImageResource(R.drawable.indicator_selected);
// 将上一个圆点设置为默认样式
ImageView prView = (ImageView) mIndicator
.getChildAt(mPreviousPos);
prView.setImageResource(R.drawable.indicator_normal);
mPreviousPos = arg0;
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
return header;
}
@Override
public void refreshView(ArrayList<String> data) {
mList = data;
mViewPager.setAdapter(new MyPagerAdapter());
mIndicator.removeAllViews();// 保险期间,先清除所有子view
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
for (int i = 0; i < mList.size(); i++) {
ImageView view = new ImageView(UIUtils.getContext());
if (i == 0) {
view.setImageResource(R.drawable.indicator_selected);
} else {
view.setImageResource(R.drawable.indicator_normal);
params.leftMargin = UIUtils.dip2px(3);// 设置圆点间距
}
mIndicator.addView(view, params);
}
}
class MyPagerAdapter extends PagerAdapter {
private BitmapUtils mBitmapUtils;
public MyPagerAdapter() {
mBitmapUtils = BitmapHelper.getBitmapUtils();
mBitmapUtils.configDefaultLoadingImage(R.drawable.subject_default);
}
@Override
public int getCount() {
return mList.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView view = new ImageView(UIUtils.getContext());
view.setScaleType(ScaleType.FIT_XY);
mBitmapUtils.display(view,
HttpHelper.URL + "image?name=" + mList.get(position));
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
}
循环滑动效果
MyPagerAdapter.java
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
int pos = position % mList.size();
}
------------------------------------
@Override
public void onPageSelected(int arg0) {
int pos = arg0 % mList.size();
// 将当前圆点设置为选中样式
ImageView view = (ImageView) mIndicator.getChildAt(pos);
view.setImageResource(R.drawable.indicator_selected);
if(pos!=mPreviousPos) {
// 将上一个圆点设置为默认样式
ImageView prView = (ImageView) mIndicator
.getChildAt(mPreviousPos);
prView.setImageResource(R.drawable.indicator_normal);
}
mPreviousPos = pos;
}
--------------------------------------
// 设置viewpager滑动的初始位置
mViewPager.setCurrentItem(mList.size() * 1000);
自动轮播效果
class RunnableTask implements Runnable {
public void start() {
// 移除之前遗留的任务(handler只有一个,但HomeFragment有可能多次被创建,
// 从而导致消息被重复发送,所以需要先把之前的消息移除掉)
UIUtils.getHandler().removeCallbacksAndMessages(null);
// 发送延时2秒的任务
UIUtils.getHandler().postDelayed(this, 2000);
}
@Override
public void run() {
// 跳到viewpager下一个页面
int currentItem = mViewPager.getCurrentItem();
currentItem++;
mViewPager.setCurrentItem(currentItem);
// 继续发送延时两秒的任务, 形成闭环, 达到循环执行的效果
UIUtils.getHandler().postDelayed(this, 2000);
}
}
// 开启自动轮播效果
new RunnableTask().start();
首页详情页 ##
首页(HomeFragment)
view.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//跳转到首页详情页面
AppInfo appInfo = mList.get(position - 1);
Intent intent = new Intent(UIUtils.getContext(),
HomeDetailActivity.class);
//将包名传递到详情页
intent.putExtra("package", appInfo.packageName);
startActivity(intent);
}
});
详情页(HomeDetailActivity)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//初始化加载页面
mLoadingPage = new LoadingPage(UIUtils.getContext()) {
@Override
public View onCreateSuccessView() {
return HomeDetailActivity.this.onCreateSuccessView();
}
@Override
public ResultState onLoad() {
return HomeDetailActivity.this.onLoad();
}
};
setContentView(mLoadingPage);
mPackageName = getIntent().getStringExtra("package");
//开始加载数据
mLoadingPage.loadData();
}
/**
- 加载网络数据
- @return
*/
public ResultState onLoad() {
HomeDetailProtocol protocol = new HomeDetailProtocol(mPackageName);
mData = protocol.getData(0);
if (mData != null) {
return ResultState.STATE_SUCCESS;
} else {
return ResultState.STATE_ERROR;
}
}
应用信息封装(AppInfo)
AppInfo新增字段
public class AppInfo {
public String des;
public String downloadUrl;
public String iconUrl;
public String id;
public String name;
public String packageName;
public long size;
public double stars;
// 以下字段共应用详情页使用
public String author;
public String date;
public String downloadNum;
public String version;
public ArrayList<SafeInfo> safe;
public ArrayList<String> screen;
public static class SafeInfo {
public String safeDes;
public int safeDesColor;
public String safeDesUrl;
public String safeUrl;
}
}
网络请求&数据解析(HomeDetailProtocol)
public class HomeDetailProtocol extends BaseProtocol<AppInfo> {
private String packageName;
public HomeDetailProtocol(String packageName) {
this.packageName = packageName;
}
@Override
public String getKey() {
return "detail";
}
@Override
public String getParams() {
return "&packageName=" + packageName;
}
@Override
public AppInfo parseJson(String result) {
try {
JSONObject jo = new JSONObject(result);
AppInfo info = new AppInfo();
info.des = jo.getString("des");
info.downloadUrl = jo.getString("downloadUrl");
info.iconUrl = jo.getString("iconUrl");
info.id = jo.getString("id");
info.name = jo.getString("name");
info.packageName = jo.getString("packageName");
info.size = jo.getLong("size");
info.stars = jo.getDouble("stars");
info.author = jo.getString("author");
info.date = jo.getString("date");
info.downloadNum = jo.getString("downloadNum");
info.version = jo.getString("version");
// 解析安全相关信息
JSONArray ja = jo.getJSONArray("safe");
ArrayList<SafeInfo> safe = new ArrayList<AppInfo.SafeInfo>();
for (int i = 0; i < ja.length(); i++) {
SafeInfo safeInfo = new SafeInfo();
JSONObject jo1 = ja.getJSONObject(i);
safeInfo.safeDes = jo1.getString("safeDes");
safeInfo.safeDesUrl = jo1.getString("safeDesUrl");
safeInfo.safeUrl = jo1.getString("safeUrl");
safeInfo.safeDesColor = jo1.getInt("safeDesColor");
safe.add(safeInfo);
}
info.safe = safe;
// 解析图片信息
JSONArray ja1 = jo.getJSONArray("screen");
ArrayList<String> screen = new ArrayList<String>();
for (int i = 0; i < ja1.length(); i++) {
String picUrl = ja1.getString(i);
screen.add(picUrl);
}
info.screen = screen;
return info;
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
详情页布局开发
思路: 用ScrollView包裹,保证可以上下滑动.每个模块使用FrameLayout作为容器,动态添加相关模块布局.
layout_home_detail.xml
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="3dp" >
<FrameLayout
android:id="@+id/fl_detail_appinfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/list_item_bg_selector" >
</FrameLayout>
<FrameLayout
android:id="@+id/fl_detail_safeinfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/list_item_bg_selector" >
</FrameLayout>
<HorizontalScrollView
android:id="@+id/hsv_detail_pics"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</HorizontalScrollView>
<FrameLayout
android:id="@+id/fl_detail_des"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</FrameLayout>
</LinearLayout>
</ScrollView>
(详情页-应用信息模块)DetailAppInfoHolder
布局文件
layout_detail_appinfo.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="wrap_content"
android:orientation="vertical"
android:padding="3dp" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp" >
<ImageView
android:id="@+id/iv_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="5dp"
android:src="@drawable/ic_default" />
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_toRightOf="@id/iv_icon"
android:singleLine="true"
android:text="京东"
android:textColor="#000"
android:textSize="18sp" />
<RatingBar
android:id="@+id/rb_star"
android:layout_width="wrap_content"
android:layout_height="16dp"
android:layout_below="@id/tv_name"
android:layout_marginTop="5dp"
android:layout_toRightOf="@id/iv_icon"
android:isIndicator="true"
android:progressDrawable="@drawable/custom_ratingbar"
android:rating="5" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="5dp"
android:paddingRight="5dp" >
<TextView
android:id="@+id/tv_download_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="下载量:100万+"
android:textColor="#9e9e9e"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="版本:1.0"
android:textColor="#9e9e9e"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="5dp"
android:paddingRight="5dp" >
<TextView
android:id="@+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="2015-08-06"
android:textColor="#9e9e9e"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="3.1MB"
android:textColor="#9e9e9e"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
界面加载&数据填充
public class DetailAppInfoHolder extends BaseHolder<AppInfo> {
private TextView tvName;
private TextView tvDownloadNum;
private TextView tvSize;
private TextView tvDate;
private TextView tvVersion;
private ImageView ivIcon;
private RatingBar rbStar;
@Override
public View initView() {
View view = View.inflate(UIUtils.getContext(),
R.layout.layout_detail_appinfo, null);
tvName = (TextView) view.findViewById(R.id.tv_name);
tvDownloadNum = (TextView) view.findViewById(R.id.tv_download_num);
tvSize = (TextView) view.findViewById(R.id.tv_size);
tvDate = (TextView) view.findViewById(R.id.tv_date);
tvVersion = (TextView) view.findViewById(R.id.tv_version);
ivIcon = (ImageView) view.findViewById(R.id.iv_icon);
rbStar = (RatingBar) view.findViewById(R.id.rb_star);
return view;
}
@Override
public void refreshView(AppInfo data) {
if (data != null) {
tvName.setText(data.name);
tvSize.setText(Formatter.formatFileSize(UIUtils.getContext(),
data.size));
tvDownloadNum.setText("下载量:" + data.downloadNum);
tvDate.setText(data.date);
tvVersion.setText("版本:" + data.version);
rbStar.setRating((float) data.stars);
BitmapHelper.getBitmapUtils().display(ivIcon,
HttpHelper.URL + "image?name=" + data.iconUrl);
}
}
}
(详情页-安全信息模块)DetailSafeInfoHolder
布局文件
思路: 安全标识部分和安全描述部分, 最多有4种情况展现, 所以提前写好4种情况, 然后通过设置显示和隐藏的方式,展示正确数量的标识和描述.标识和描述的勾选框都是服务器返回的图片,需要网络加载.
layout_detail_safeinfo.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rl_safe_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/iv_safe1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp" />
<ImageView
android:id="@+id/iv_safe2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:layout_toRightOf="@id/iv_safe1" />
<ImageView
android:id="@+id/iv_safe3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:layout_toRightOf="@id/iv_safe2" />
<ImageView
android:id="@+id/iv_safe4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:layout_toRightOf="@id/iv_safe3" />
<ImageView
android:id="@+id/iv_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_margin="5dp"
android:src="@drawable/arrow_down" />
</RelativeLayout>
<LinearLayout
android:id="@+id/ll_des_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp" >
<LinearLayout
android:id="@+id/ll_des1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<ImageView
android:id="@+id/iv_des1"
android:layout_width="20dp"
android:layout_height="20dp" />
<TextView
android:id="@+id/tv_des1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="#9e9e9e"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_des2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<ImageView
android:id="@+id/iv_des2"
android:layout_width="20dp"
android:layout_height="20dp" />
<TextView
android:id="@+id/tv_des2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="#9e9e9e"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_des3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<ImageView
android:id="@+id/iv_des3"
android:layout_width="20dp"
android:layout_height="20dp" />
<TextView
android:id="@+id/tv_des3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="#9e9e9e"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_des4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<ImageView
android:id="@+id/iv_des4"
android:layout_width="20dp"
android:layout_height="20dp" />
<TextView
android:id="@+id/tv_des4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="#9e9e9e"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
布局加载&数据填充
public class DetailAppSafeHolder extends BaseHolder<AppInfo> {
private ImageView[] ivSafes;// 安全标识的控件数组
private LinearLayout[] llDes;// 安全描述控件数组
private ImageView[] ivDes;// 安全描述图片控件数组
private TextView[] tvDes;// 安全描述文字控件数组
private LinearLayout llDesRoot;// 安全描述根布局
private BitmapUtils mBitmapUtils;
private int mDesRootHeight;// 安全描述整体布局高度
private LayoutParams mParams;// 安全描述整体控件布局参数
private boolean isExpanded = false;// 标记当前安全描述打开还是关闭的状态
private ImageView ivArrow;// 安全标识小箭头
@Override
public View initView() {
View view = View.inflate(UIUtils.getContext(),
R.layout.layout_detail_safeinfo, null);
ivSafes = new ImageView[4];
ivSafes[0] = (ImageView) view.findViewById(R.id.iv_safe1);
ivSafes[1] = (ImageView) view.findViewById(R.id.iv_safe2);
ivSafes[2] = (ImageView) view.findViewById(R.id.iv_safe3);
ivSafes[3] = (ImageView) view.findViewById(R.id.iv_safe4);
llDes = new LinearLayout[4];
llDes[0] = (LinearLayout) view.findViewById(R.id.ll_des1);
llDes[1] = (LinearLayout) view.findViewById(R.id.ll_des2);
llDes[2] = (LinearLayout) view.findViewById(R.id.ll_des3);
llDes[3] = (LinearLayout) view.findViewById(R.id.ll_des4);
ivDes = new ImageView[4];
ivDes[0] = (ImageView) view.findViewById(R.id.iv_des1);
ivDes[1] = (ImageView) view.findViewById(R.id.iv_des2);
ivDes[2] = (ImageView) view.findViewById(R.id.iv_des3);
ivDes[3] = (ImageView) view.findViewById(R.id.iv_des4);
tvDes = new TextView[4];
tvDes[0] = (TextView) view.findViewById(R.id.tv_des1);
tvDes[1] = (TextView) view.findViewById(R.id.tv_des2);
tvDes[2] = (TextView) view.findViewById(R.id.tv_des3);
tvDes[3] = (TextView) view.findViewById(R.id.tv_des4);
ivArrow = (ImageView) view.findViewById(R.id.iv_arrow);
// 设置安全描述整体布局高度为0, 达到隐藏效果
llDesRoot = (LinearLayout) view.findViewById(R.id.ll_des_root);
mParams = llDesRoot.getLayoutParams();
mParams.height = 0;
llDesRoot.setLayoutParams(mParams);
// 设置安全标识整体控件的点击事件
view.findViewById(R.id.rl_safe_root).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
// 展开或者收起安全描述信息
toggle();
}
});
mBitmapUtils = BitmapHelper.getBitmapUtils();
return view;
}
@Override
public void refreshView(AppInfo data) {
if (data != null) {
ArrayList<SafeInfo> safe = data.safe;
if (safe != null) {
for (int i = 0; i < 4; i++) {
if (i < safe.size()) {
SafeInfo safeInfo = safe.get(i);
ivSafes[i].setVisibility(View.VISIBLE);
llDes[i].setVisibility(View.VISIBLE);
tvDes[i].setText(safeInfo.safeDes);
mBitmapUtils.display(ivSafes[i], HttpHelper.URL
“image?name=” + safeInfo.safeUrl);
mBitmapUtils.display(ivDes[i], HttpHelper.URL
“image?name=” + safeInfo.safeDesUrl);
} else {
ivSafes[i].setVisibility(View.GONE);
llDes[i].setVisibility(View.GONE);
}
}
}
// 计算安全描述布局的整体高度
llDesRoot.measure(0, 0);
mDesRootHeight = llDesRoot.getMeasuredHeight();
}
}
展开收起动画效果
/**
-
展开或者收起安全描述信息
*/
protected void toggle() {
// 需要引入nineoldandroids.jar,可以兼容api11以下的版本
ValueAnimator animator;
if (isExpanded) {
// 收起描述信息
isExpanded = false;
// 初始化按指定值变化的动画器, 布局高度从mDesRootHeight变化到0,此方法调用,并开启动画之后,
// 会将最新的高度值不断回调在onAnimationUpdate方法中,在onAnimationUpdate中更新布局高度
animator = ValueAnimator.ofInt(mDesRootHeight, 0);
} else {
// 展开描述信息
isExpanded = true;
// 初始化按指定值变化的动画器, 布局高度从0变化到mDesRootHeight
animator = ValueAnimator.ofInt(0, mDesRootHeight);
}// 设置动画更新的监听 animator.addUpdateListener(new AnimatorUpdateListener() { // 在动画开始以后,每次动画有了最新的状态都会回调此方法 @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { // 获取当前最新的高度信息 Integer height = (Integer) valueAnimator.getAnimatedValue(); mParams.height = height; // 更新安全描述的高度 llDesRoot.setLayoutParams(mParams); } }); // 设置动画监听 animator.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator arg0) { // 动画开始 } @Override public void onAnimationRepeat(Animator arg0) { // 动画重复 } @Override public void onAnimationEnd(Animator arg0) { // 动画结束 // 更新安全标识小箭头方向 if (isExpanded) { ivArrow.setImageResource(R.drawable.arrow_up); } else { ivArrow.setImageResource(R.drawable.arrow_down); } } @Override public void onAnimationCancel(Animator arg0) { // 动画取消 } }); // 设置动画时间 animator.setDuration(200); // 开启动画 animator.start(); }