zoukankan      html  css  js  c++  java
  • 【Android】纯代码创建页面布局(含异步加载图片)

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

    先看看总体效果

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

    【界面结构】

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

     1 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
     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     <LinearLayout
     8         android:id="@+id/frg_home"
     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 </ScrollView>

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

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

    项目结构如下:

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

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

    整个 divider 的代码如下:

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

    【代码结构】

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

     1 import android.graphics.drawable.Drawable;
     2 import android.os.Handler;
     3 
     4 import java.lang.ref.SoftReference;
     5 import java.net.URL;
     6 import java.util.HashMap;
     7 import java.util.Map;
     8 import java.util.concurrent.ExecutorService;
     9 import java.util.concurrent.Executors;
    10 
    11 public class TestImage {
    12     // 为了加快速度,在内存中开启缓存
    13     // 主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动
    14     public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
    15 
    16     // 固定 10 个线程来执行任务
    17     private ExecutorService _exeService = Executors.newFixedThreadPool(10);
    18     private final Handler _handler = new Handler();
    19 
    20     public Drawable getImage(final String url, final Callback callback) {
    21 
    22         // 缓存中存在就用缓存中的图片
    23         if (imageCache.containsKey(url)) {
    24             SoftReference<Drawable> softReference = imageCache.get(url);
    25 
    26             if (softReference.get() != null) {
    27                 return softReference.get();
    28             }
    29         }
    30 
    31         // 缓存中没有图片,就从网络中获取图片,同时,存入缓存
    32         _exeService.submit(new Runnable() {
    33 
    34             @Override
    35             public void run() {
    36                 final Drawable drawable = getImage(url);
    37                 imageCache.put(url, new SoftReference<Drawable>(drawable));
    38 
    39                 _handler.post(new Runnable() {
    40 
    41                     @Override
    42                     public void run() {
    43                         callback.imageLoaded(drawable);
    44                     }
    45                 });
    46             }
    47         });
    48 
    49         return null;
    50     }
    51 
    52     // 从网络中获取图片
    53     protected Drawable 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         return drawable;
    63     }
    64 
    65     // 回调方法
    66     public interface Callback {
    67         void imageLoaded(Drawable drawable);
    68     }
    69 }

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

     1 public class HomeFrg extends Fragment {
     2 
     3     private LinearLayout _layout;
     4     //private TestImage _testImage = new TestImage();
     5 
     6     public HomeFrg() {
     7         // Required empty public constructor
     8     }
     9 
    10     @Override
    11     public View 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         return view;
    18     }
    19 
    20     private void initView(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 void initCell(View view) {
    29         Context self = this.getContext();
    30 
    31         // 创建单个的单元格的容器(RelativeLayout)
    32         RelativeLayout.LayoutParams layoutWrapper = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    33         RelativeLayout wrapper = new RelativeLayout(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 = new ImageView(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 = new RelativeLayout.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 = new TextView(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 = new RelativeLayout.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 = new TextView(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 = new RelativeLayout.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 = new TextView(self);
    80         txtTime.setText("2016年9月22日 16:33");
    81         wrapper.addView(txtTime, layoutTime);
    82     }
    83 
    84     // 再次封装 TestImage,实现异步加载,方便页面内调用
    85     private void loadImage(String url, final ImageView imageView) {
    86         Drawable imgCache = new TestImage().getImage(url, new TestImage.Callback() {
    87 
    88             @Override
    89             public void imageLoaded(Drawable drawable) {
    90                 imageView.setImageDrawable(drawable);
    91             }
    92         });
    93 
    94         if (imgCache != null) {
    95             imageView.setImageDrawable(imgCache);
    96         }
    97     }
    98 }

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

    【特别说明】

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

    1、声明 LayoutParams layout

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

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

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

  • 相关阅读:
    Log4Net学习【三】
    Log4Net学习【二】
    Log4Net学习【一】
    Asp.Net生命周期系列六
    Asp.Net生命周期系列五
    Asp.Net生命周期系列四
    Asp.Net生命周期系列三
    我为什么很烦在DB服务器上安装杀毒软件
    SQL Server 2012故障转移的looksalive check和is alive check
    如何让用户只能访问特定的数据库(MSSQL)
  • 原文地址:https://www.cnblogs.com/jacksonwj/p/5930161.html
Copyright © 2011-2022 走看看