【Android】纯代码创建页面布局(含异步加载图片)
开发环境: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】纯代码创建页面布局(含异步加载图片)的更多相关文章
- Android学习笔记(二)之异步加载图片
最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出.我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片.开发android应用的朋友可能或多或少碰到加载图片内存 ...
- wemall app商城源码中基于JAVA的Android异步加载图片管理器代码
wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...
- 实例演示Android异步加载图片
本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...
- 实例演示Android异步加载图片(转)
本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...
- Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
Android 高手进阶(21) 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处http://blog.csdn.net/xiaanming/article/details ...
- Android之ListView异步加载图片且仅显示可见子项中的图片
折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整 ...
- Android GridView异步加载图片和加载大量图片时出现Out Of Memory问题
我们在使用GridView或者ListView时,通常会遇到两个棘手的问题: 1.每个Item获取的数据所用的时间太长会导致程序长时间黑屏,更甚会导致程序ANR,也就是Application No R ...
- Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案
我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...
- Android 实现ListView异步加载图片
ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; ...
随机推荐
- Android权限管理之Permission权限机制及使用
前言: 最近突然喜欢上一句诗:"宠辱不惊,看庭前花开花落:去留无意,望天空云卷云舒." 哈哈~,这个和今天的主题无关,最近只要不学习总觉得生活中少了点什么,所以想着围绕着最近面试过 ...
- [转载]一个标准java程序员的进阶过程
第一阶段:Java程序员 技术名称 内 容 说明 Java语法基础 基本语法.数组.类.继承.多态.抽象类.接口.object对象.常用类(Math\Arrarys\S ...
- 微服务与Docker介绍
什么是微服务 微服务应用的一个最大的优点是,它们往往比传统的应用程序更有效地利用计算资源.这是因为它们通过扩展组件来处理功能瓶颈问题.这样一来,开发人员只需要为额外的组件部署计算资源,而不需要部署一个 ...
- 对Maven、gradle、svn、spring 3.0 fragment、git的想法
1.Maven Maven可以构建项目,采用pom方式配置主项目和其他需要引用的项目.同时可结合spring3.0的新特性web fragment. 从现实出发,特别是对于管理不到位,程序员整体素质 ...
- Hibernate 系列 学习笔记 目录 (持续更新...)
前言: 最近也在学习Hibernate,遇到的问题差不多都解决了,顺便把学习过程遇到的问题和查找的资料文档都整理了一下分享出来,也算是能帮助更多的朋友们了. 最开始使用的是经典的MyEclipse,后 ...
- redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作
前段时间在做用户画像的时候,遇到了这样的一个问题,记录某一个商品的用户购买群,刚好这种需求就可以用到Redis中的Set,key作为productID,value 就是具体的customerid集合, ...
- Java
2016-12-17 21:10:28 吉祥物:Duke(公爵) Logo:咖啡(爪哇岛盛产咖啡) An overview of the software development proce ...
- MyBatis4:动态SQL
什么是动态SQL MyBatis的一个强大特性之一通常是它的动态SQL能力.如果你有使用JDBC或其他相似框架的经验,你就明白条件串联SQL字符串在一起是多么地痛苦,确保不能忘了空格或者在列表的最后的 ...
- 感悟 GNU C 以及将 Vim 打造成 C/C++ 的半自动化 IDE
C 语言在 Linux 系统中的重要性自然是无与伦比.不可替代,所以我写 Linux 江湖系列不可能不提 C 语言.C 语言是我的启蒙语言,感谢 C 语言带领我进入了程序世界.虽然现在不靠它吃饭,但是 ...
- [MongoDB] 32Bit构建上文件大小限制问题
一. 问题概述 今天看看爬虫抓取的数据,发现数据无法插入,首先想到的就是32Bit构建的文件大小限制问题,检查一下还真的是.本文把整个检查问题,解决问题的过程记录下来. 问题: "s ...