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

先看看总体效果

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

【界面结构】

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

 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
tools:context=".Fragment.HomeFrg">
<LinearLayout
android:id="@+id/frg_home"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:divider="@drawable/sep_home"
android:showDividers="middle" />
</ScrollView>

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

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

项目结构如下:

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

 <color name="colorBG">#EEEEEE</color>

整个 divider 的代码如下:

 <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/colorBG" />
<size android:height="10dp" />
</shape>

【代码结构】

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

 import android.graphics.drawable.Drawable;
import android.os.Handler; import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class TestImage {
// 为了加快速度,在内存中开启缓存
// 主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动
public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>(); // 固定 10 个线程来执行任务
private ExecutorService _exeService = Executors.newFixedThreadPool(10);
private final Handler _handler = new Handler(); public Drawable getImage(final String url, final Callback callback) { // 缓存中存在就用缓存中的图片
if (imageCache.containsKey(url)) {
SoftReference<Drawable> softReference = imageCache.get(url); if (softReference.get() != null) {
return softReference.get();
}
} // 缓存中没有图片,就从网络中获取图片,同时,存入缓存
_exeService.submit(new Runnable() { @Override
public void run() {
final Drawable drawable = getImage(url);
imageCache.put(url, new SoftReference<Drawable>(drawable)); _handler.post(new Runnable() { @Override
public void run() {
callback.imageLoaded(drawable);
}
});
}
}); return null;
} // 从网络中获取图片
protected Drawable getImage(String url) {
Drawable drawable = null; try {
drawable = Drawable.createFromStream(new URL(url).openStream(), "img.png");
} catch (Exception e) {
e.printStackTrace();
} return drawable;
} // 回调方法
public interface Callback {
void imageLoaded(Drawable drawable);
}
}

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

 public class HomeFrg extends Fragment {

     private LinearLayout _layout;
//private TestImage _testImage = new TestImage(); public HomeFrg() {
// Required empty public constructor
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frg_home, container, false);
initView(view); // Inflate the layout for this fragment
return view;
} private void initView(View view) {
_layout = (LinearLayout) view.findViewById(R.id.frg_home); for (int i = 0; i < 3; i++) {
initCell(view);
}
} private void initCell(View view) {
Context self = this.getContext(); // 创建单个的单元格的容器(RelativeLayout)
RelativeLayout.LayoutParams layoutWrapper = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
RelativeLayout wrapper = new RelativeLayout(self);
wrapper.setBackgroundColor(Helper.getColor(self, R.color.colorWhite));
wrapper.setPadding(0, 30, 0, 30);
_layout.addView(wrapper, layoutWrapper); // 创建封面图片(ImageView)
RelativeLayout.LayoutParams layoutCover = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 600);
ImageView imgCover = new ImageView(self);
int idCover = view.generateViewId();
imgCover.setId(idCover);
// 异步加载网络图片(图片URL为测试图片)
loadImage("http://pic9.nipic.com/20100904/4845745_195609329636_2.jpg", imgCover);
imgCover.setScaleType(ImageView.ScaleType.CENTER_CROP);
imgCover.setPadding(20, 0, 20, 0);
wrapper.addView(imgCover, layoutCover); // 创建标题(TextView)
RelativeLayout.LayoutParams layoutTitle = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutTitle.setMargins(20, 0, 20, 0);
layoutTitle.addRule(RelativeLayout.BELOW, idCover);
TextView txtTitle = new TextView(self);
int idTitle = view.generateViewId();
txtTitle.setId(idTitle);
txtTitle.setText("标题内容标题内容标题内容标题内容标题内容标题内容");
txtTitle.setTextSize(20);
// 标题单行显示,多余的字符用省略号代替(包括以下两行)
txtTitle.setEllipsize(TextUtils.TruncateAt.END);
txtTitle.setSingleLine();
txtTitle.setTextColor(Helper.getColor(self, R.color.colorBlack));
wrapper.addView(txtTitle, layoutTitle); // 创建作者(TextView)
RelativeLayout.LayoutParams layoutAuthor = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutAuthor.setMargins(20, 0, 20, 0);
layoutAuthor.addRule(RelativeLayout.BELOW, idTitle);
TextView txtAuthor = new TextView(self);
int idAuthor = view.generateViewId();
txtAuthor.setId(idAuthor);
txtAuthor.setText("作者名称");
txtAuthor.setTextColor(Helper.getColor(self, R.color.colorBlack));
wrapper.addView(txtAuthor, layoutAuthor); // 创建日期(TextView)
RelativeLayout.LayoutParams layoutTime = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutTime.setMargins(20, 0, 20, 0);
layoutTime.addRule(RelativeLayout.BELOW, idAuthor);
TextView txtTime = new TextView(self);
txtTime.setText("2016年9月22日 16:33");
wrapper.addView(txtTime, layoutTime);
} // 再次封装 TestImage,实现异步加载,方便页面内调用
private void loadImage(String url, final ImageView imageView) {
Drawable imgCache = new TestImage().getImage(url, new TestImage.Callback() { @Override
public void imageLoaded(Drawable drawable) {
imageView.setImageDrawable(drawable);
}
}); if (imgCache != null) {
imageView.setImageDrawable(imgCache);
}
}
}

至此,所有功能实现完毕。

【特别说明】

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

1、声明 LayoutParams layout

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

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

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

【Android】纯代码创建页面布局(含异步加载图片)的更多相关文章

  1. Android学习笔记(二)之异步加载图片

    最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出.我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片.开发android应用的朋友可能或多或少碰到加载图片内存 ...

  2. wemall app商城源码中基于JAVA的Android异步加载图片管理器代码

    wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...

  3. 实例演示Android异步加载图片

    本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...

  4. 实例演示Android异步加载图片(转)

    本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...

  5. Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅

      Android 高手进阶(21)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处http://blog.csdn.net/xiaanming/article/details ...

  6. Android之ListView异步加载图片且仅显示可见子项中的图片

    折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整 ...

  7. Android GridView异步加载图片和加载大量图片时出现Out Of Memory问题

    我们在使用GridView或者ListView时,通常会遇到两个棘手的问题: 1.每个Item获取的数据所用的时间太长会导致程序长时间黑屏,更甚会导致程序ANR,也就是Application No R ...

  8. Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案

    我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...

  9. Android 实现ListView异步加载图片

    ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; ...

随机推荐

  1. 06.SQLServer性能优化之---数据库级日记监控

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 之前说了一下数据库怎么发邮件:http://www.cnblogs.com/duniti ...

  2. Dapper扩展之~~~Dapper.Contrib

    平台之大势何人能挡? 带着你的Net飞奔吧!http://www.cnblogs.com/dunitian/p/4822808.html#skill 上一篇文章:Dapper逆天入门~强类型,动态类型 ...

  3. ExtJS 4.2 组件介绍

    目录 1. 介绍 1.1 说明 1.2 组件分类 1.3 组件名称 1.4 组件结构 2. 组件的创建方式 2.1 Ext.create()创建 2.2 xtype创建 1. 介绍 1.1 说明 Ex ...

  4. 这些.NET开源项目你知道吗?.NET平台开源文档与报表处理组件集合(三)

    在前2篇文章这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧 和这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,大伙热情高涨.再次拿出自己的私货,在.NET平台 ...

  5. iOS开发之再探多线程编程:Grand Central Dispatch详解

    Swift3.0相关代码已在github上更新.之前关于iOS开发多线程的内容发布过一篇博客,其中介绍了NSThread.操作队列以及GCD,介绍的不够深入.今天就以GCD为主题来全面的总结一下GCD ...

  6. 最好的.NET开源免费ZIP库DotNetZip(.NET组件介绍之三)

    在项目开发中,除了对数据的展示更多的就是对文件的相关操作,例如文件的创建和删除,以及文件的压缩和解压.文件压缩的好处有很多,主要就是在文件传输的方面,文件压缩的好处就不需要赘述,因为无论是开发者,还是 ...

  7. Maven 代理设置

    在maven的安装目录下 %MAVEN_HOME%/conf/setting.xml 中进行设置 <proxies>    <!-- proxy     | Specificatio ...

  8. 面向对象相关知识点xmind

  9. css3更改input单选和多选的样式

    在项目开发中我们经常会遇到需要更改input单选和多选样式的情况,今天就给大家介绍一种简单改变input单选和多选样式的办法. 在这之前先简单介绍一下:before伪类 :before 选择器向选定的 ...

  10. 计算Div标签内Checkbox个数或已被disabled的个数

    先看下面的html: 计算div内的checkbox个数:$('#divmod input[type="checkbox"]').length 计算div内checkbox被dis ...