开发环境:macOS 10.12 + Android Studio 2.2,MinSDK Android 5.1java

先看看整体效果android

android页面从左到右_java

本示例是基于Fragment进行的,直接上代码:缓存

【界面结构】网络

在 Fragment 中,采用 ScrollView + LinearLayout 实现。app

1 
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:scrollbars="vertical"
6 tools:context=".Fragment.HomeFrg">
7 
9 android:layout_width="match_parent"
10 android:layout_height="match_parent"
11 android:orientation="vertical"
12 android:divider="@drawable/sep_home"
13 android:showDividers="middle" />
14

顺便说一句,显示列表中的分割线,采用自身的divider来实现,实现方式见上述代码中的第十二、13行。异步

分割线采用 drawable 的 shape,注意:shape 中必定要添加 solid 和 size,而且 solid 的颜色必须定义,哪怕是透明的也要定义。ide

项目结构以下:布局

android页面从左到右_android页面布局代码实现方法_02

背景颜色的定义,在 values/colors 中实现,以下所示:post

1 #EEEEEE

整个 divider 的代码以下:测试

1 <?xml version="1.0" encoding="utf-8"?>

【代码结构】

新建 java 的类库,名为:TestImage.java,主要是结合缓存实现图片的异步加载(线程池方式),代码以下:

1 importandroid.graphics.drawable.Drawable;2 importandroid.os.Handler;3
4 importjava.lang.ref.SoftReference;5 importjava.net.URL;6 importjava.util.HashMap;7 importjava.util.Map;8 importjava.util.concurrent.ExecutorService;9 importjava.util.concurrent.Executors;10
11 public classTestImage {12 //为了加快速度,在内存中开启缓存13 //主要应用于重复图片较多时,或者同一个图片要屡次被访问,好比在ListView时来回滚动
14 public Map> imageCache = new HashMap>();15
16 //固定 10 个线程来执行任务
17 private ExecutorService _exeService = Executors.newFixedThreadPool(10);18 private final Handler _handler = newHandler();19
20 public Drawable getImage(final String url, finalCallback callback) {21
22 //缓存中存在就用缓存中的图片
23 if(imageCache.containsKey(url)) {24 SoftReference softReference =imageCache.get(url);25
26 if (softReference.get() != null) {27 returnsoftReference.get();28 }29 }30
31 //缓存中没有图片,就从网络中获取图片,同时,存入缓存
32 _exeService.submit(newRunnable() {33
34 @Override35 public voidrun() {36 final Drawable drawable =getImage(url);37 imageCache.put(url, new SoftReference(drawable));38
39 _handler.post(newRunnable() {40
41 @Override42 public voidrun() {43 callback.imageLoaded(drawable);44 }45 });46 }47 });48
49 return null;50 }51
52 //从网络中获取图片
53 protectedDrawable getImage(String url) {54 Drawable drawable = null;55
56 try{57 drawable = Drawable.createFromStream(new URL(url).openStream(), "img.png");58 } catch(Exception e) {59 e.printStackTrace();60 }61
62 returndrawable;63 }64
65 //回调方法
66 public interfaceCallback {67 voidimageLoaded(Drawable drawable);68 }69 }

类库创建好了以后,在 Fragment 的后台代码中进行调用(含代码建立页面布局),代码以下:

1 public class HomeFrg extendsFragment {2
3 privateLinearLayout _layout;4 //private TestImage _testImage = new TestImage();
5
6 publicHomeFrg() {7 //Required empty public constructor
8 }9
10 @Override11 publicView onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {13 View view = inflater.inflate(R.layout.frg_home, container, false);14 initView(view);15
16 //Inflate the layout for this fragment
17 returnview;18 }19
20 private voidinitView(View view) {21 _layout =(LinearLayout) view.findViewById(R.id.frg_home);22
23 for (int i = 0; i < 3; i++) {24 initCell(view);25 }26 }27
28 private voidinitCell(View view) {29 Context self = this.getContext();30
31 //建立单个的单元格的容器(RelativeLayout)
32 RelativeLayout.LayoutParams layoutWrapper = newRelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);33 RelativeLayout wrapper = newRelativeLayout(self);34 wrapper.setBackgroundColor(Helper.getColor(self, R.color.colorWhite));35 wrapper.setPadding(0, 30, 0, 30);36 _layout.addView(wrapper, layoutWrapper);37
38 //建立封面图片(ImageView)
39 RelativeLayout.LayoutParams layoutCover = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 600);40 ImageView imgCover = newImageView(self);41 int idCover =view.generateViewId();42 imgCover.setId(idCover);43 //异步加载网络图片(图片URL为测试图片)
44 loadImage("http://pic9.nipic.com/20100904/4845745_195609329636_2.jpg", imgCover);45 imgCover.setScaleType(ImageView.ScaleType.CENTER_CROP);46 imgCover.setPadding(20, 0, 20, 0);47 wrapper.addView(imgCover, layoutCover);48
49 //建立标题(TextView)
50 RelativeLayout.LayoutParams layoutTitle = newRelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);51 layoutTitle.setMargins(20, 0, 20, 0);52 layoutTitle.addRule(RelativeLayout.BELOW, idCover);53 TextView txtTitle = newTextView(self);54 int idTitle =view.generateViewId();55 txtTitle.setId(idTitle);56 txtTitle.setText("标题内容标题内容标题内容标题内容标题内容标题内容");57 txtTitle.setTextSize(20);58 //标题单行显示,多余的字符用省略号代替(包括如下两行)
59 txtTitle.setEllipsize(TextUtils.TruncateAt.END);60 txtTitle.setSingleLine();61 txtTitle.setTextColor(Helper.getColor(self, R.color.colorBlack));62 wrapper.addView(txtTitle, layoutTitle);63
64 //建立做者(TextView)
65 RelativeLayout.LayoutParams layoutAuthor = newRelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);66 layoutAuthor.setMargins(20, 0, 20, 0);67 layoutAuthor.addRule(RelativeLayout.BELOW, idTitle);68 TextView txtAuthor = newTextView(self);69 int idAuthor =view.generateViewId();70 txtAuthor.setId(idAuthor);71 txtAuthor.setText("做者名称");72 txtAuthor.setTextColor(Helper.getColor(self, R.color.colorBlack));73 wrapper.addView(txtAuthor, layoutAuthor);74
75 //建立日期(TextView)
76 RelativeLayout.LayoutParams layoutTime = newRelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);77 layoutTime.setMargins(20, 0, 20, 0);78 layoutTime.addRule(RelativeLayout.BELOW, idAuthor);79 TextView txtTime = newTextView(self);80 txtTime.setText("2016年9月22日 16:33");81 wrapper.addView(txtTime, layoutTime);82 }83
84 //再次封装 TestImage,实现异步加载,方便页面内调用
85 private void loadImage(String url, finalImageView imageView) {86 Drawable imgCache = new TestImage().getImage(url, newTestImage.Callback() {87
88 @Override89 public voidimageLoaded(Drawable drawable) {90 imageView.setImageDrawable(drawable);91 }92 });93
94 if (imgCache != null) {95 imageView.setImageDrawable(imgCache);96 }97 }98 }

至此,全部功能实现完毕。

【特别说明】

上述代码在建立布局时,若是碰到最终效果,多个控件(包括 ImageView 和 TextView)重叠时,那是因为 RelativeLayout 的布局的特殊性,须要声明几个关键的东西:

一、声明 LayoutParams layout

二、控件.setId(view.generateViewId())

三、layout.addRule(RelativeLayout.BELOW, 上述 generateViewId() 所产生的 Id)

注意以上三点,便可在 RelativeLayout 中,将各个控件依次分开排列布局。同时,可经过 layout.setMargins 或 控件.setPadding 进行各处留白距离的微调。