前四天, 完成了整个页面的显示。今天,就只做了详情页面的显示。
有事情要去兰州市里一趟....
运行效果图:
通过运行效果图来看,我们观察到详情页面的布局是特别复杂的,因此我们必须具体分析详情页面。
这里我将详情页面分为5个部分:信息区域,安全区域,截图区域,介绍区域,底部区域。
我们将这个5个部分的布局抽取出来,分工完成,然后依次添加到详情页面的布局之中。这5个子布局分别对应着相应的Holder.
因此,以后我们遇到这种复杂的布局的时候,可以拆分为几部分,分别完成。如果写在一个xml文件中,就会显得臃肿,不便于维护。
看代码:
HomeFragment.java
package com.example.fragment;
import java.util.List;
import android.content.Intent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.btt.ui.widget.LoadingPager.LoadResult;
import com.example.DetailActivity;
import com.example.adapter.MyBaseAdapter;
import com.example.bean.AppInfo;
import com.example.holder.BaseHolder;
import com.example.holder.HomeHolder;
import com.example.protocol.HomeProtocol;
import com.example.utils.UIUtils;
public class HomeFragment extends BaseFragment {
private List<AppInfo> mDatas;
@Override
protected View createSuccessView() {
ListView mListView = new ListView(UIUtils.getContext());
MyBaseAdapter adapter = new HomeAdapter(mDatas,mListView);
mListView.setAdapter(adapter);
return mListView;
}
@Override
protected LoadResult load() {
HomeProtocol protocol = new HomeProtocol();
mDatas = protocol.load(0);
return check(mDatas);
}
private class HomeAdapter<T> extends MyBaseAdapter implements OnItemClickListener{
public HomeAdapter(List<T> mDatas, ListView mListView) {
super(mDatas);
mListView.setOnItemClickListener(this);
}
@Override
public BaseHolder getHolder() {
return new HomeHolder();
}
@Override
public List onLoadMore() {
HomeProtocol protocol = new HomeProtocol();
return protocol.load(getDatas().size());
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Intent intent = new Intent(UIUtils.getContext(), DetailActivity.class);
String packageName = mDatas.get(position).getPackageName();
intent.putExtra(DetailActivity.PACKAGENAME, packageName);
startActivity(intent);
}
}
}
package com.example;
import android.content.Intent;
import android.support.v7.app.ActionBar;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import com.btt.ui.widget.LoadingPager;
import com.btt.ui.widget.LoadingPager.LoadResult;
import com.example.bean.AppInfo;
import com.example.holder.AppDetailBottomHolder;
import com.example.holder.AppDetailDesHolder;
import com.example.holder.AppDetailInfoHolder;
import com.example.holder.AppDetailSafeHolder;
import com.example.holder.AppDetailScreenHolder;
import com.example.protocol.DetailProtocol;
import com.example.utils.StringUtils;
import com.example.utils.UIUtils;
public class DetailActivity extends BaseActivity {
public static final String PACKAGENAME = "PACKAGENAME";
private AppInfo mAppInfo;
private String mPackageName;
private ActionBar mActionBar;
//各区域布局及其holder
private FrameLayout mInfoLayout, mSafeLayout, mDesLayout, mBottomLayout;
private HorizontalScrollView mScreenLayout;
private AppDetailInfoHolder mInfoHolder;
private AppDetailSafeHolder mSafeHolder;
private AppDetailScreenHolder mScreenHolder;
private AppDetailDesHolder mDesHolder;
private AppDetailBottomHolder mBottomHolder;
@Override
public void init() {
Intent i = getIntent();
if (i != null) {//从意图中获取packageName用户从服务端获取数据
mPackageName = i.getStringExtra(PACKAGENAME);
}
}
/** 初始化actionBar */
public void initActionBar() {
mActionBar = getSupportActionBar();
}
/** 初始化布局 */
public void initView() {
LoadingPager mContentView = new LoadingPager(this) {
@Override
public LoadResult load() {
return DetailActivity.this.load();
}
@Override
public View createSuccessView() {
return DetailActivity.this.createSuccessView();
}
};
setContentView(mContentView);
mContentView.show();
}
/** 加载数据 */
private LoadResult load() {
DetailProtocol protocol = new DetailProtocol();
protocol.setPackageName(mPackageName);
mAppInfo = protocol.load(0);
if (mAppInfo == null || StringUtils.isEmpty(mAppInfo.getPackageName())) {
return LoadResult.ERROR;
}
return LoadResult.SUCCESS;
}
/** 获取数据后的显示的View */
private View createSuccessView() {
View view = UIUtils.inflate(R.layout.activity_detail);
// 添加信息区域
mInfoLayout = (FrameLayout) view.findViewById(R.id.detail_info);
mInfoHolder = new AppDetailInfoHolder();
mInfoHolder.setData(mAppInfo);
mInfoLayout.addView(mInfoHolder.getRootView());
// 添加安全区域
mSafeLayout = (FrameLayout) view.findViewById(R.id.detail_safe);
mSafeHolder = new AppDetailSafeHolder();
mSafeHolder.setData(mAppInfo);
mSafeLayout.addView(mSafeHolder.getRootView());
// 截图区域
mScreenLayout = (HorizontalScrollView) view.findViewById(R.id.detail_screen);
mScreenHolder = new AppDetailScreenHolder();
mScreenHolder.setData(mAppInfo);
mScreenLayout.addView(mScreenHolder.getRootView());
// 介绍区域
mDesLayout = (FrameLayout) view.findViewById(R.id.detail_des);
mDesHolder = new AppDetailDesHolder();
mDesHolder.setData(mAppInfo);
mDesLayout.addView(mDesHolder.getRootView());
// 底部区域
mBottomLayout = (FrameLayout) view.findViewById(R.id.bottom_layout);
mBottomHolder = new AppDetailBottomHolder();
mBottomHolder.setData(mAppInfo);
mBottomLayout.addView(mBottomHolder.getRootView());
mBottomHolder.startObserver();
return view;
}
}
activity_detail.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/bottom_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="@drawable/detail_bottom_bg" >
</FrameLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottom_layout"
android:layout_marginBottom="5dp"
android:fillViewport="true" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/detail_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="@drawable/list_item_bg_normal" />
<FrameLayout
android:id="@+id/detail_safe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/detail_info"
android:background="@drawable/list_item_bg_normal" />
<HorizontalScrollView
android:id="@+id/detail_screen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/detail_safe"
android:background="@color/detail_screen_bg"
android:fillViewport="true"
android:padding="5dp"
android:scrollbars="none" />
<FrameLayout
android:id="@+id/detail_des"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/detail_screen"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="@drawable/list_item_bg_normal" />
</RelativeLayout>
</ScrollView>
</RelativeLayout>
DetailProtocol.java
package com.example.protocol;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import com.example.bean.AppInfo;
import com.example.utils.LogUtils;
import com.example.utils.StringUtils;
public class DetailProtocol extends BaseProtocol<AppInfo> {
private String mPackageName = "";
public void setPackageName(String packageName) {
mPackageName = packageName;
}
@Override
protected String getKey() {
return "detail";
}
@Override
protected String getParames() {
if (StringUtils.isEmpty(mPackageName)) {
return super.getParames();
} else {
return "&packageName=" + mPackageName;
}
}
@Override
protected AppInfo parseFromJson(String json) {
try {
JSONObject obj = new JSONObject(json);
AppInfo info = new AppInfo();
info.setId(obj.getLong("id"));
info.setName(obj.getString("name"));
info.setPackageName(obj.getString("packageName"));
info.setIconUrl(obj.getString("iconUrl"));
info.setStars(Float.valueOf(obj.getString("stars")));
info.setDownloadNum(obj.getString("downloadNum"));
info.setVersion(obj.getString("version"));
info.setDate(obj.getString("date"));
info.setSize(obj.getLong("size"));
info.setDownloadUrl(obj.getString("downloadUrl"));
info.setDes(obj.getString("des"));
info.setAuthor(obj.getString("author"));
JSONArray array = obj.getJSONArray("screen");
List<String> screens = new ArrayList<String>();
for (int i = 0; i < array.length(); i++) {
String screen = array.getString(i);
screens.add(screen);
}
info.setScreen(screens);
array = obj.getJSONArray("safe");
List<String> safeUrlList = new ArrayList<String>();
List<String> safeDesUrlList = new ArrayList<String>();
List<String> safeDesList = new ArrayList<String>();
List<Integer> safeDesColorList = new ArrayList<Integer>();
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
String safeUrl = object.getString("safeUrl");
String safeDesUrl = object.getString("safeDesUrl");
String safeDes = object.getString("safeDes");
Integer safeDesColor = object.getInt("safeDesColor");
safeUrlList.add(safeUrl);
safeDesUrlList.add(safeDesUrl);
safeDesList.add(safeDes);
safeDesColorList.add(safeDesColor);
}
info.setSafeUrl(safeUrlList);
info.setSafeDesUrl(safeDesUrlList);
info.setSafeDes(safeDesList);
info.setSafeDesColor(safeDesColorList);
return info;
} catch (Exception e) {
LogUtils.e(e);
return null;
}
}
}
AppDetailInfoHolder.java
package com.example.holder;
import android.view.View;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.TextView;
import com.example.R;
import com.example.bean.AppInfo;
import com.example.image.ImageLoader;
import com.example.utils.StringUtils;
import com.example.utils.UIUtils;
public class AppDetailInfoHolder extends BaseHolder<AppInfo> {
private ImageView mIcon;
private TextView mTitleTxt, mDownloadTxt, mViesionTxt, mDateTxt, mSizeTxt;
private RatingBar mRating;
@Override
public View initView() {
View view = UIUtils.inflate(R.layout.app_detail_info);
mIcon = (ImageView) view.findViewById(R.id.item_icon);
mRating = (RatingBar) view.findViewById(R.id.item_rating);
mTitleTxt = (TextView) view.findViewById(R.id.item_title);
mDownloadTxt = (TextView) view.findViewById(R.id.item_download);
mViesionTxt = (TextView) view.findViewById(R.id.item_version);
mDateTxt = (TextView) view.findViewById(R.id.item_date);
mSizeTxt = (TextView) view.findViewById(R.id.item_size);
return view;
}
@Override
public void refershView() {
AppInfo info = getData();
String url = info.getIconUrl();
mIcon.setTag(url);
ImageLoader.load(mIcon, url);
mRating.setRating(info.getStars());
mTitleTxt.setText(info.getName());
mDownloadTxt.setText(UIUtils.getString(R.string.app_detail_download) + info.getDownloadNum());
mViesionTxt.setText(UIUtils.getString(R.string.app_detail_version) + info.getVersion());
mDateTxt.setText(UIUtils.getString(R.string.app_detail_date) + info.getDate());
mSizeTxt.setText(UIUtils.getString(R.string.app_detail_size) + StringUtils.formatFileSize(info.getSize()));
}
}
app_detail_info.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_info_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<RelativeLayout
android:id="@+id/item_top"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:src="@drawable/ic_default"
android:id="@+id/item_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerVertical="true"
android:layout_marginRight="8dp"
android:scaleType="fitXY"/>
<RelativeLayout
android:id="@+id/item_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/item_icon">
<TextView
android:id="@+id/item_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#ff333333"
android:textSize="16dp"/>
<RatingBar
android:id="@+id/item_rating"
android:layout_width="wrap_content"
android:layout_height="@dimen/list_item_rating_height"
android:layout_below="@id/item_title"
android:layout_marginTop="@dimen/app_detail_rating_margin"
android:isIndicator="true"
android:progressDrawable="@drawable/ratingbar_small"
android:rating="2.5"/>
</RelativeLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/item_top"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
android:id="@+id/item_download"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#ff7a7a7a"
android:textSize="12dp"/>
<TextView
android:id="@+id/item_version"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#ff7a7a7a"
android:textSize="12dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
android:id="@+id/item_date"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#ff7a7a7a"
android:textSize="12dp"/>
<TextView
android:id="@+id/item_size"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#ff7a7a7a"
android:textSize="12dp"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
AppDetailSafeHolder.java
package com.example.holder;
import java.util.List;
import android.graphics.Color;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.example.R;
import com.example.bean.AppInfo;
import com.example.image.ImageLoader;
import com.example.utils.UIUtils;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.Animator.AnimatorListener;
import com.nineoldandroids.animation.ValueAnimator;
public class AppDetailSafeHolder extends BaseHolder<AppInfo> implements OnClickListener {
private RelativeLayout mSafeLayout;
private LinearLayout mContentLayout;
private ImageView mArrow;
private ImageView[] mIv;
private ImageView[] mDesIv;
private TextView[] mDesTv;
private LinearLayout[] mLayout;
@Override
public View initView() {
View view = UIUtils.inflate(R.layout.app_detail_safe);
mSafeLayout = (RelativeLayout) view.findViewById(R.id.safe_layout);
mContentLayout = (LinearLayout) view.findViewById(R.id.safe_content);
//默认进来是关闭的
mContentLayout.getLayoutParams().height = 0;
mArrow = (ImageView) view.findViewById(R.id.safe_arrow);
mArrow.setTag(false);
mSafeLayout.setOnClickListener(this);
mIv = new ImageView[4];
mIv[0] = (ImageView) view.findViewById(R.id.iv_1);
mIv[1] = (ImageView) view.findViewById(R.id.iv_2);
mIv[2] = (ImageView) view.findViewById(R.id.iv_3);
mIv[3] = (ImageView) view.findViewById(R.id.iv_4);
mDesIv = new ImageView[4];
mDesIv[0] = (ImageView) view.findViewById(R.id.des_iv_1);
mDesIv[1] = (ImageView) view.findViewById(R.id.des_iv_2);
mDesIv[2] = (ImageView) view.findViewById(R.id.des_iv_3);
mDesIv[3] = (ImageView) view.findViewById(R.id.des_iv_4);
mDesTv = new TextView[4];
mDesTv[0] = (TextView) view.findViewById(R.id.des_tv_1);
mDesTv[1] = (TextView) view.findViewById(R.id.des_tv_2);
mDesTv[2] = (TextView) view.findViewById(R.id.des_tv_3);
mDesTv[3] = (TextView) view.findViewById(R.id.des_tv_4);
mLayout = new LinearLayout[4];
mLayout[0] = (LinearLayout) view.findViewById(R.id.des_layout_1);
mLayout[1] = (LinearLayout) view.findViewById(R.id.des_layout_2);
mLayout[2] = (LinearLayout) view.findViewById(R.id.des_layout_3);
mLayout[3] = (LinearLayout) view.findViewById(R.id.des_layout_4);
return view;
}
@Override
public void refershView() {
AppInfo info = getData();
//对应着官方。安全。无广告等的图片下载地址
List<String> safeUrl = info.getSafeUrl();
//小框框打勾的下载地址
List<String> safeDesUrl = info.getSafeDesUrl();
//小框框打勾后面的描述信息
List<String> safeDes = info.getSafeDes();
//描述的文字颜色,有广告的颜色比较醒目
List<Integer> safeDesColor = info.getSafeDesColor();
for (int i = 0; i < 4; i++) {
if (i < safeUrl.size() && i < safeDesUrl.size() && i < safeDes.size() && i < safeDesColor.size()) {
ImageLoader.load(mIv[i], safeUrl.get(i));
ImageLoader.load(mDesIv[i], safeDesUrl.get(i));
mDesTv[i].setText(safeDes.get(i));
int color;
int colorType = safeDesColor.get(i);
if (colorType >= 1 && colorType <= 3) {
color = Color.rgb(255, 153, 0);
} else if (colorType == 4) {
color = Color.rgb(0, 177, 62);
} else {
color = Color.rgb(122, 122, 122);
}
mDesTv[i].setTextColor(color);
mIv[i].setVisibility(View.VISIBLE);
mLayout[i].setVisibility(View.VISIBLE);
} else {
mIv[i].setVisibility(View.GONE);
mLayout[i].setVisibility(View.GONE);
}
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.safe_layout:
expand();
break;
default:
break;
}
}
private void expand() {
final LayoutParams params = mContentLayout.getLayoutParams();
int targetHeight;
int height = mContentLayout.getMeasuredHeight();
boolean flag = (Boolean) mArrow.getTag();
if (flag) {
mArrow.setTag(false);
targetHeight = 0;
} else {
mArrow.setTag(true);
targetHeight = measureContentHeight();
}
mSafeLayout.setEnabled(false);
ValueAnimator va = ValueAnimator.ofInt(height, targetHeight);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator va) {
params.height = (Integer) va.getAnimatedValue();
mContentLayout.setLayoutParams(params);
}
});
va.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator arg0) {
}
@Override
public void onAnimationRepeat(Animator arg0) {
}
@Override
public void onAnimationEnd(Animator arg0) {
boolean flag = (Boolean) mArrow.getTag();
mArrow.setImageResource(flag ? R.drawable.arrow_up : R.drawable.arrow_down);
mSafeLayout.setEnabled(true);
}
@Override
public void onAnimationCancel(Animator arg0) {
}
});
va.setDuration(300);
va.start();
}
private int measureContentHeight() {
int width = mContentLayout.getMeasuredWidth();
mContentLayout.getLayoutParams().height = LayoutParams.WRAP_CONTENT;
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(1000, MeasureSpec.AT_MOST);
mContentLayout.measure(widthMeasureSpec, heightMeasureSpec);
return mContentLayout.getMeasuredHeight();
}
}
app_detail_safe.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/safe_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<RelativeLayout
android:id="@+id/safe_title_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<LinearLayout
android:id="@+id/safe_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"/>
<ImageView
android:id="@+id/iv_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:scaleType="centerInside"/>
<ImageView
android:id="@+id/iv_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:scaleType="centerInside"/>
<ImageView
android:id="@+id/iv_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:scaleType="centerInside"/>
</LinearLayout>
<ImageView
android:id="@+id/safe_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:scaleType="centerInside"
android:src="@drawable/arrow_down"/>
</RelativeLayout>
<LinearLayout
android:id="@+id/safe_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/safe_title_layout"
android:orientation="vertical">
<LinearLayout
android:id="@+id/des_layout_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/des_iv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"/>
<TextView
android:id="@+id/des_tv_1"
android:layout_marginLeft="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#ff7a7a7a"
android:textSize="12dp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/des_layout_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/des_iv_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"/>
<TextView
android:id="@+id/des_tv_2"
android:layout_marginLeft="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#ff7a7a7a"
android:textSize="12dp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/des_layout_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/des_iv_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"/>
<TextView
android:id="@+id/des_tv_3"
android:layout_marginLeft="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#ff7a7a7a"
android:textSize="12dp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/des_layout_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/des_iv_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"/>
<TextView
android:id="@+id/des_tv_4"
android:layout_marginLeft="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#ff7a7a7a"
android:textSize="12dp"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
AppDetailScreenHolder.java
package com.example.holder;
import android.view.View;
import android.widget.ImageView;
import com.example.R;
import com.example.bean.AppInfo;
import com.example.image.ImageLoader;
import com.example.utils.UIUtils;
public class AppDetailScreenHolder extends BaseHolder<AppInfo> {
private ImageView[] mIv;
@Override
public View initView() {
View view = UIUtils.inflate(R.layout.app_detail_screen);
mIv = new ImageView[5];
mIv[0] = (ImageView) view.findViewById(R.id.screen_1);
mIv[1] = (ImageView) view.findViewById(R.id.screen_2);
mIv[2] = (ImageView) view.findViewById(R.id.screen_3);
mIv[3] = (ImageView) view.findViewById(R.id.screen_4);
mIv[4] = (ImageView) view.findViewById(R.id.screen_5);
return view;
}
@Override
public void refershView() {
AppInfo info = getData();
for (int i = 0; i < 5; i++) {
if (i < info.getScreen().size()) {
ImageLoader.load(mIv[i], info.getScreen().get(i));
mIv[i].setVisibility(View.VISIBLE);
} else {
mIv[i].setVisibility(View.GONE);
}
}
}
}
app_detail_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/screen_1"
android:layout_width="90dp"
android:layout_height="150dp"
android:paddingRight="5dp"
android:src="@drawable/ic_default"
android:scaleType="fitXY" />
<ImageView
android:id="@+id/screen_2"
android:layout_width="90dp"
android:layout_height="150dp"
android:src="@drawable/ic_default"
android:layout_toRightOf="@id/screen_1"
android:paddingRight="5dp"
android:scaleType="fitXY"/>
<ImageView
android:id="@+id/screen_3"
android:layout_width="90dp"
android:layout_height="150dp"
android:layout_toRightOf="@id/screen_2"
android:src="@drawable/ic_default"
android:paddingRight="5dp"
android:scaleType="fitXY" />
<ImageView
android:id="@+id/screen_4"
android:layout_width="90dp"
android:layout_height="150dp"
android:layout_toRightOf="@id/screen_3"
android:paddingRight="5dp"
android:src="@drawable/ic_default"
android:scaleType="fitXY"/>
<ImageView
android:id="@+id/screen_5"
android:layout_width="90dp"
android:layout_height="150dp"
android:src="@drawable/ic_default"
android:layout_toRightOf="@id/screen_4"
android:paddingRight="5dp"
android:scaleType="fitXY" />
</RelativeLayout>
AppDetailDesHolder.java
package com.example.holder;
import android.util.TypedValue;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.example.R;
import com.example.bean.AppInfo;
import com.example.utils.UIUtils;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.Animator.AnimatorListener;
import com.nineoldandroids.animation.ValueAnimator;
public class AppDetailDesHolder extends BaseHolder<AppInfo> implements OnClickListener {
private RelativeLayout mLayout;
private TextView mContent, mAuthor;
private ImageView mArrow;
private ScrollView mScrollView;
private boolean mIsInit = true;
@Override
public View initView() {
View view = UIUtils.inflate(R.layout.app_detail_des);
mContent = (TextView) view.findViewById(R.id.des_content);
mAuthor = (TextView) view.findViewById(R.id.des_author);
mLayout = (RelativeLayout) view.findViewById(R.id.des_layout);
mLayout.setOnClickListener(this);
mArrow = (ImageView) view.findViewById(R.id.des_arrow);
mArrow.setTag(false);
return view;
}
@Override
public void refershView() {
AppInfo info = getData();
mContent.setText(info.getDes());
mAuthor.setText(UIUtils.getString(R.string.app_detail_author) + info.getAuthor());
if (mIsInit) {
mContent.getLayoutParams().height = measureShortHeight();
mIsInit = false;
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.des_layout:
expand();
break;
default:
break;
}
}
private void expand() {
final LayoutParams params = mContent.getLayoutParams();
int shortHeight = measureShortHeight();
int longHeight = measureLongHeight();
ValueAnimator va;
final boolean flag = (Boolean) mArrow.getTag();
if (flag) {
mArrow.setTag(false);
va = ValueAnimator.ofInt(longHeight, shortHeight);
} else {
mArrow.setTag(true);
va = ValueAnimator.ofInt(shortHeight, longHeight);
}
mLayout.setEnabled(false);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator va) {
params.height = (Integer) va.getAnimatedValue();
mContent.setLayoutParams(params);
if (!flag) {
if (mScrollView == null) {
mScrollView = getScrollView();
}
if (mScrollView != null) {
mScrollView.scrollTo(0, mScrollView.getHeight());
}
}
}
});
va.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator arg0) {
}
@Override
public void onAnimationRepeat(Animator arg0) {
}
@Override
public void onAnimationEnd(Animator arg0) {
boolean flag = (Boolean) mArrow.getTag();
mArrow.setImageResource(flag ? R.drawable.arrow_up : R.drawable.arrow_down);
mLayout.setEnabled(true);
}
@Override
public void onAnimationCancel(Animator arg0) {
}
});
va.setDuration(300);
va.start();
}
private int measureShortHeight() {
int width = mContent.getMeasuredWidth();
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(2000, MeasureSpec.AT_MOST);
TextView tv = getTextView();
tv.setLines(7);
tv.setMaxLines(7);
tv.measure(widthMeasureSpec, heightMeasureSpec);
return tv.getMeasuredHeight();
}
private int measureLongHeight() {
int width = mContent.getMeasuredWidth();
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(2000, MeasureSpec.AT_MOST);
TextView tv = getTextView();
tv.measure(widthMeasureSpec, heightMeasureSpec);
return tv.getMeasuredHeight();
}
private TextView getTextView() {
TextView tv = new TextView(UIUtils.getContext());
tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
tv.setText(getData().getDes());
return tv;
}
private ScrollView getScrollView() {
ScrollView scroView = null;
View currentView = mLayout;
while (true) {
ViewParent parent = currentView.getParent();
if (parent == null || !(parent instanceof View)) {
break;
} else if (parent instanceof ScrollView) {
scroView = (ScrollView) parent;
break;
} else {
currentView = (View) parent;
}
}
return scroView;
}
}
app_detail_des.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/des_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">
<TextView
android:id="@+id/des_titile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:text="@string/app_detail_introduction"
android:textColor="#3c3c3c"
android:textSize="14dp"/>
<TextView
android:id="@+id/des_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/des_titile"
android:layout_marginTop="5dp"
android:textColor="#7a7a7a"
android:textSize="14dp"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/des_content"
android:layout_marginTop="5dp"
android:gravity="center_vertical">
<TextView
android:id="@+id/des_author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:singleLine="true"
android:textColor="#b3b3b3"
android:textSize="14dp"/>
<ImageView
android:id="@+id/des_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:scaleType="centerInside"
android:src="@drawable/arrow_down"/>
</RelativeLayout>
</RelativeLayout>
AppDetailBottomHolder.java
package com.example.holder;
import android.graphics.Color;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
import com.btt.ui.widget.ProgressHorizontal;
import com.example.R;
import com.example.bean.AppInfo;
import com.example.bean.DownloadInfo;
import com.example.manage.DownloadManager;
import com.example.utils.UIUtils;
public class AppDetailBottomHolder extends BaseHolder<AppInfo> implements OnClickListener, DownloadManager.DownloadObserver {
private Button mBtnFavorites, mBtnShare, mBtnProgress;
private FrameLayout mLayout;
private ProgressHorizontal mProgeressView;
private float mProgress;
private DownloadManager mDownloadManager;
private int mState;
@Override
public View initView() {
View view = UIUtils.inflate(R.layout.app_detail_bottom);
mBtnFavorites = (Button) view.findViewById(R.id.bottom_favorites);
mBtnShare = (Button) view.findViewById(R.id.bottom_share);
mBtnProgress = (Button) view.findViewById(R.id.progress_btn);
mBtnFavorites.setOnClickListener(this);
mBtnShare.setOnClickListener(this);
mBtnProgress.setOnClickListener(this);
mBtnFavorites.setText(R.string.bottom_favorites);
mBtnShare.setText(R.string.bottom_share);
mLayout = (FrameLayout) view.findViewById(R.id.progress_layout);
mProgeressView = new ProgressHorizontal(UIUtils.getContext());
mProgeressView.setId(R.id.detail_progress);
mProgeressView.setOnClickListener(this);
mProgeressView.setProgressTextVisible(true);
mProgeressView.setProgressTextColor(Color.WHITE);
mProgeressView.setProgressTextSize(UIUtils.dip2px(18));
mProgeressView.setBackgroundResource(R.drawable.progress_bg);
mProgeressView.setProgressResource(R.drawable.progress);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mLayout.addView(mProgeressView, params);
return view;
}
@Override
public void setData(AppInfo data) {
if (mDownloadManager == null) {
mDownloadManager = DownloadManager.getInstance();
}
DownloadInfo downloadInfo = mDownloadManager.getDownloadInfo(data.getId());
if (downloadInfo != null) {
mState = downloadInfo.getDownloadState();
mProgress = downloadInfo.getProgress();
} else {
mState = DownloadManager.STATE_NONE;
mProgress = 0;
}
super.setData(data);
}
@Override
public void refershView() {
refreshState(mState, mProgress);
}
public void refreshState(int state, float progress) {
mState = state;
mProgress = progress;
switch (mState) {
case DownloadManager.STATE_NONE:
mProgeressView.setVisibility(View.GONE);
mBtnProgress.setVisibility(View.VISIBLE);
mBtnProgress.setText(UIUtils.getString(R.string.app_state_download));
break;
case DownloadManager.STATE_PAUSED:
mProgeressView.setVisibility(View.VISIBLE);
mProgeressView.setProgress(progress);
mProgeressView.setCenterText(UIUtils.getString(R.string.app_state_paused));
mBtnProgress.setVisibility(View.GONE);
break;
case DownloadManager.STATE_ERROR:
mProgeressView.setVisibility(View.GONE);
mBtnProgress.setVisibility(View.VISIBLE);
mBtnProgress.setText(R.string.app_state_error);
break;
case DownloadManager.STATE_WAITING:
mProgeressView.setVisibility(View.VISIBLE);
mProgeressView.setProgress(progress);
mProgeressView.setCenterText(UIUtils.getString(R.string.app_state_waiting));
mBtnProgress.setVisibility(View.GONE);
break;
case DownloadManager.STATE_DOWNLOADING:
mProgeressView.setVisibility(View.VISIBLE);
mProgeressView.setProgress(progress);
mProgeressView.setCenterText("");
mBtnProgress.setVisibility(View.GONE);
break;
case DownloadManager.STATE_DOWNLOADED:
mProgeressView.setVisibility(View.GONE);
mBtnProgress.setVisibility(View.VISIBLE);
mBtnProgress.setText(R.string.app_state_downloaded);
break;
default:
break;
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bottom_favorites:
UIUtils.showToastSafe(R.string.bottom_favorites);
break;
case R.id.bottom_share:
UIUtils.showToastSafe(R.string.bottom_share);
break;
case R.id.progress_btn:
case R.id.detail_progress:
if (mState == DownloadManager.STATE_NONE || mState == DownloadManager.STATE_PAUSED || mState == DownloadManager.STATE_ERROR) {
mDownloadManager.download(getData());
} else if (mState == DownloadManager.STATE_WAITING || mState == DownloadManager.STATE_DOWNLOADING) {
mDownloadManager.pause(getData());
} else if (mState == DownloadManager.STATE_DOWNLOADED) {
mDownloadManager.install(getData());
}
break;
default:
break;
}
}
public void startObserver() {
mDownloadManager.registerObserver(this);
}
public void stopObserver() {
mDownloadManager.unRegisterObserver(this);
}
@Override
public void onDownloadStateChanged(DownloadInfo info) {
refreshHolder(info);
}
@Override
public void onDownloadProgressed(DownloadInfo info) {
refreshHolder(info);
}
private void refreshHolder(final DownloadInfo info) {
AppInfo appInfo = getData();
if (appInfo.getId() == info.getId()) {
UIUtils.runInMainThread(new Runnable() {
@Override
public void run() {
refreshState(info.getDownloadState(), info.getProgress());
}
});
}
}
}
app_detail_bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bottom_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/bottom_favorites"
android:layout_width="68dp"
android:layout_height="38dp"
android:layout_alignParentLeft="true"
android:layout_margin="6dp"
android:background="@drawable/detail_btn"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="16dp" />
<Button
android:id="@+id/bottom_share"
android:layout_width="68dp"
android:layout_height="38dp"
android:layout_alignParentRight="true"
android:layout_margin="6dp"
android:background="@drawable/detail_btn"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="16dp" />
<FrameLayout
android:id="@+id/progress_layout"
android:layout_width="match_parent"
android:layout_height="38dp"
android:layout_centerVertical="true"
android:layout_toLeftOf="@id/bottom_share"
android:layout_toRightOf="@id/bottom_favorites" >
</FrameLayout>
<Button
android:id="@+id/progress_btn"
android:layout_width="match_parent"
android:layout_height="38dp"
android:layout_centerVertical="true"
android:layout_toLeftOf="@id/bottom_share"
android:layout_toRightOf="@id/bottom_favorites"
android:background="@drawable/progress_btn"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="18dp" >
</Button>
</RelativeLayout>
代码不怎么多,这些代码写起来也简单,因为我们已经把思路理清了,再说前面已经把框架搭建好了,就没什么难的了。