Microsoft Word - Android App开发从入门到精通.doc

Size: px
Start display at page:

Download "Microsoft Word - Android App开发从入门到精通.doc"

Transcription

1 第 2 章 Android 控件 本章主要介绍 Android 中常用的控件及其使用方法,Android SDK 本身给我们提供大量的 UI 控件, 合理熟练地使用这些控件才能做出优美的界面 有时候 Android 自带的控件不一定能满足业务需求, 所以本章还会介绍自定义控件 2.1 View 介绍 在 Android 开发中,Android 的 UI 界面都是由 View 及其派生类组合而成的 View 类几乎包 含了所有的屏幕类型, 每一个 View 都有一个用于绘图的画布 画布可以进行任意扩展, 只需要重 写 ondraw 方法, 就能绘制界面显示 界面既可以是复杂的 3D 效果, 也可以只是简单的文本显示 表 2-1 描述了 View 常用的 XML 属性及相关方法 表 2-1 View 常用的 XML 属性及相关方法 XML 属性 相关方法 说明 android:id setid(int) 给当前 View 设置一个在当前 xxx.xml 中的唯一编号, 可以通过调用 View.findViewById() 或 Activity.findViewById() 根据编号查找到对应的 View 不同的 layout.xml 之间定义相同的 id 不会冲突 android:clickable setclickable(boolean clickable) 是否响应点击事件 clickable=true: 允许 clickable=false: 禁止 android:longclickable setlongclickable(boolean clickable) 是否响应长点击事件 clickable=true: 允许 clickable=false: 禁止

2 54 Android App 开发从入门到精通 ( 续表 ) XML 属性 相关方法 说明 android:backgroud setbackgroundcolor 设置背景颜色 android:visibility setvisibility 是否可见 Visible: 默认值, 可见 Invisible: 不可见 Gone: 不可见, 并且在屏幕中不占位置 android:scrollbars 设置滚动条显示 None: 隐藏, 不可见 Horizontal: 水平 Vertical: 垂直 android:onclick 在 xml 中给 onclik 设置什么值, 在对应的 Activity 中写对应的方法 例如 : android:onclick="test", 在 Activity 中写对应的方法 设置点击事件 public void test(view view){ android:padding setpadding(int,int,int,int) 设置上下左右内边距 android:paddingtop 设置顶部内边距 android:paddingbottom 设置底部内边距 android:paddingleft 设置左边内边距 android:paddingright 设置右边内边距 android:layout_margin 设置外边距 android:layout_margintop 设置顶部外边距 android:layout_marginbottom 设置底部外边距 android:layout_marginleft 设置左边外边距 android:layout_marginright 设置右边外边距 android:minheight setminimumheight(int) 设置视图最小高度 android:minwidth setminimumwidth(int) 设置视图最小宽度 View 是所有 UI 组件的基类 一般来说, 开发 Android 应用程序的 UI 界面都不会直接使用 View, 而是使用派生类 View 派生出的直接子类有 ImageView TextView ViewGroup ProgressBar 等 View 派生出的间接子类有 AbsListView Button Edittext CheckBox 等 使用系统给我们提供的 View 派生类能实现开发中的大部分需求, 但是有时候需要针对业务需 求去定制 View, 例如画饼状图 折线图 贝塞尔曲线等 自定义 View 我们要实现的效果就是一个画圆的过程, 在增加圆形弧度的同时改变圆的颜色 ( 颜色随机生

3 第 2 章 Android 控件 55 成 ) 如果弧度大于 360, 就重新开始画, 一直循环 每次增加的弧度根据 xml 文件设置, 不需要修改 Java 代码, 运行效果如图 2-1 所示 图 2-1 自定义 View 运行效果 新建一个项目, 在项目下建一个 MyView 类, 继承自 View 重写构造方法和 ondraw 方法 public class MyView extends View{ private MyThread mythread; private Paint paint;// 画笔 private RectF rectf=new RectF(150,150,380,380); private int sweepangle=0;// 弧的当前度数 private int sweepangleadd=20;// 弧每次增加度数 private Random random=new Random(); private boolean running=true;// 控制循环 public MyView(Context context) { this(context,null); public MyView(Context context,attributeset attrs) { super(context, attrs); init(context,attrs); // 初始化 private void init(context context,attributeset attrs){ paint=new Paint(); paint.settextsize(60); protected void ondraw(canvas canvas){

4 56 Android App 开发从入门到精通 Log.i("MyView","onDraw"); if(null==mythread){ mythread=new MyThread(); mythread.start(); else{ // 第一个参数是 RectF 左上的 x y 坐标右下的 x y 坐标 // 第二个参数是弧形的开始角度 // 第三个参数是弧形的结束角度 // 第四个参数是 true: 画扇形 false: 画弧线 // 第五个参数是画笔 canvas.drawarc(rectf, 0, sweepangle, true, paint); // 开启一个子线程绘制 ui private class MyThread extends Thread{ public void run() { while(running){ logic(); postinvalidate();// 重新绘制, 会调用 ondraw try { Thread.sleep(200); catch (InterruptedException e) { e.printstacktrace(); protected void logic() { sweepangle+=sweepangleadd;// 每次增加弧度 // 随机设置画笔的颜色 int r=random.nextint(255); int g=random.nextint(255); int b=random.nextint(255); paint.setargb(255, r, g, b); if(sweepangle>=360){// 如果弧度大于 360 就从头开始 sweepangle=0; protected void ondetachedfromwindow() { running=false;// 销毁 View 的时候设置成 false, 退出无限循环 super.ondetachedfromwindow(); 我们在构造方法中初始化画笔,View 第一次绘制在界面上时会调用 ondraw 方法 我们首先判断当前的线程是否为空, 第一次运行 mythread 肯定是空的, 于是开启线程 如果不为空就绘制圆

5 第 2 章 Android 控件 57 启动 MyThread 线程时, 会调用 run 方法 在 run 方法中用一个变量控制循环, 默认是 true, 只要我们没有改变这个变量的值为 false, 就是一个死循环 在循环中调用 logic 方法, 同时调用 View 自带的 postinvalidate 方法重新绘制界面 最后延迟 200 毫秒 logic 方法中增加圆形的弧度, 设置画笔的颜色 最后判断一下弧度是不是大于 360, 如果大于 360 就从 0 重新开始 ondetachedfromwindow 方法是 View 生命周期里面的一个方法, 在 View 销毁的时候调用 改变 running 变量的值为 false, 这样线程就会退出死循环 1. View 测量 ( 重写 onmeasure 方法 ) 讲到 View 的 measure 测量, 会涉及 View 的一个静态内部类 MeasureSpec,MeasureSpec 类封装了父 View 传递给子 View 的布局 (layout) 要求, 每个 MeasureSpec 实例代表宽度或者高度 ( 只能是其一 ) 要求 MeasureSpec 的字面意思是测量规格或者测量属性, 在 measure 方法中有两个参数 widthmeasurespec 和 heightmeasurespec 如果使用 widthmeasurespec, 我们就可以通过 MeasureSpec 计算出宽度模式 Mode 和宽度的实际值 测量的模式分以下三种 : EXACTLY: 精确值模式 当 View 的 layout_width 或者 layout_height 属性设置为具体的数值 ( 例如,android:layout_width = "100dp") 或者指定为 match_parent 时 ( 系统会自动分配为父布局的大小 ) 使用的模式 AT_MOST : 最大值模式 当 View 的 layout_width 或者 layout_height 属性设置为 wrap_content 时使用的模式 UNSPECIFIED: 可以将视图按照自己的意愿设置成任意大小, 没有任何限制 这种情况比较少见, 很少用到 2. 为什么要重写 onmeasure 方法 我们修改一下 activity_main.xml: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" res/android" android:layout_height="match_parent"> <com.ansen.view.myview android:background="@android:color/holo_green_ dark" /> </RelativeLayout> 最外层用 RelativeLayout, 里面用了我们自定义的 View, 运行效果如图 2-3 所示 图 2-3 未重写 onmeasure 方法运行效果图

6 58 Android App 开发从入门到精通 从布局文件中可以看到明明设置了 android:layout_ width="wrap_content", 但是背景颜色的宽高跟屏幕一样大 所以我们得重写 onmeasure 方法 : protected void onmeasure(int widthmeasurespec, int heightmeasurespec){ // 获得父容器为它设置的测量模式和大小 int widthmode = MeasureSpec.getMode(widthMeasureSpec); int widthsize = MeasureSpec.getSize(widthMeasureSpec); int heightmode = MeasureSpec.getMode(heightMeasureSpec); int heightsize = MeasureSpec.getSize(heightMeasureSpec); int width; int height ; if (widthmode == MeasureSpec.EXACTLY){// 指定宽度或者 match_parent width = widthsize; else{ width = (int) (getpaddingleft() + getpaddingright() + rectf.width()*2); if (heightmode == MeasureSpec.EXACTLY){// 指定高度或者 match_parent height = heightsize; else{ height = (int) (getpaddingtop()+getpaddingbottom()+rectf.height()*2); setmeasureddimension(width, height); 首先获取宽高模式以及父容器为这个 View 分配的宽高, 然后判断宽高的类型, 因为在布局文件中设置的是 wrap_content, 所以都会执行 else 语句 宽度是圆形的 2 倍, 高度也是圆形的 2 倍,View 的宽高只有是圆形的两倍才能看到圆形以外的绿色背景 最后调用 setmeasureddimension 传入测量之后的宽高 重新运行代码, 效果如图 2-4 所示 从效果图中可以看到显示正常 为什么我们的圆形画在背景颜色区域的右下角? 因为 RectF 的 left 跟 top 都是从 190 开始的 如果想画在左上角应该怎么做呢? 其实很简单, 只需要修改 RectF 的初始值即可 private RectF rectf=new RectF(0,0,190,190); 这样改了之后就从 (0,0) 坐标画圆, 并且圆形的宽高还是 190 View 的宽高是圆形的两倍, 还是 自定义属性 图 2-4 重写 onmeasure 方法后运行效果图 首先在 res/values 下新建一个 attrs.xml 文件 内容如下 :

7 <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="customstyleview"> <attr name="sweepangleadd" format="integer"/> </declare-styleable> </resources> 第 2 章 Android 控件 59 其中,name 为属性集的名字, 主要用途是标识属性集 ;attr 标签可以有多个 ;format 属性对应的类型也有很多, 例如 string integer dimension reference color enum, 这里使用 integer 在布局 xml 文件中引用我们刚刚自定义的属性 activity_main.xml 在修改之后的内容如下 : <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" xmlns:custom=" android:layout_height="match_parent"> <com.ansen.view.myview android:background="@android:color/holo_green_dark" custom:sweepangleadd="10"/> </RelativeLayout> 这里只增加了两行代码, 即最外层的 RelativeLayout 增加了自定义 View 的命名空间 之后, 在自定义 View 中就可以使用 custom:sweepangleadd 属性了 接下来在 MyView 类的 init 方法中获取 sweepangleadd 的值 // 获取自定义属性的值 TypedArray typedarray=context.obtainstyledattributes(attrs, R.styleable.customStyleView); sweepangleadd=typedarray.getint(r.styleable.customstyleview_sweepangleadd, 0); typedarray.recycle(); 这样做的好处就是如果我们想改变圆形每次增加的弧度大小, 只需要修改 xml 文件即可, 不需要修改自定义 View 的 Java 代码, 达到封装的效果 2.2 ViewGroup 介绍 做过 Android 应用开发的朋友都知道,Android 的 UI 界面都是由 View 和 ViewGroup 及其派生类组合而成的 其中,View 是所有 UI 组件的基类, 而 ViewGroup 是容纳这些组件的容器, 其本身也是从 View 派生出来的 AndroidUI 界面的一般结构可参见图 2-5 可见, 作为容器的 ViewGroup 可以包含作为叶子节点的 View, 也可以包含作为更低层次的子 ViewGroup, 而子 ViewGroup 又可以包含下一层的叶子节点的 View 和 ViewGroup 事实上, 这种灵活的 View 层次结构可以形成非常复杂的 UI 布局, 开发者可据此设计 开发非常精致的 UI 界面

8 60 Android App 开发从入门到精通 图 2-5 ViewGroup 如何在布局中形成分支并容纳其他 View 的图解一般来说, 开发 Android 应用程序的 UI 界面都不会直接使用 ViewGroup, 而是使用它的派生类 ViewGroup 派生出的直接子类有 CoordinatorLayout DrawerLayout RecyclerView,FrameLayou LinearLayout RelativeLayout SwipeRefreshLayout ViewPager 等 ViewGroup 派生出的间接子类有 GridView ListView,WebView 等 自定义 ViewGroup 在前面的内容中, 我们学习过如何自定义 View 自定义 ViewGroup 跟自定义 View 有点类似 一般情况下自定义 ViewGroup 会重写以下几个方法 : onmeasure 测量子 View 的宽高, 根据子 View 的宽高与自己的测量模式来决定自己的宽高 onlayout 决定子 View 的摆放位置 generatelayoutparams 根据子 View 的布局参数决定子 View 在当前容器的摆放位置, 这个方法根据需求决定要不要重写 1. 首先实现 LinearLayout 布局的水平排列效果 实现这种效果只需要重写 onlayout 和 onmeasure 方法, 这里新建一个类 MyViewGroup, 继承自 ViewGroup public class MyViewGroup extends ViewGroup{ public MyViewGroup(Context context) { super(context); public MyViewGroup(Context context, AttributeSet attrs) { super(context,attrs); protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { // 获取 ViewGroup 宽高 int sizewidth = MeasureSpec.getSize(widthMeasureSpec); int sizeheight = MeasureSpec.getSize(heightMeasureSpec);

9 第 2 章 Android 控件 61 measurechildren(widthmeasurespec,heightmeasurespec); // 测量所有子 View 的宽高 Log.i("ansen"," 测量宽度 :"+sizewidth+" 测量高度 :"+sizeheight); setmeasureddimension(sizewidth,sizeheight); protected void onlayout(boolean changed, int l, int t, int r, int b) { int count=getchildcount();// 获取子 View 数量 int left=0; for(int i=0;i<count;i++){ View child=getchildat(i); int childwidth=child.getmeasuredwidth();// 获取子 View 宽度 int childheight=child.getmeasuredheight();// 获取子 View 高度 child.layout(left,0,left+childwidth,childheight);// 设置摆放位置 left+=childwidth;// 执行流程是在 onmeasure 方法调用两遍之后再调用 onlayout 方法 首先我们看 onmeasure 方法, 跟之前自定义 View 时有点类似, 没有使用过的就只有 measurechildren 方法 measurechildren 方法的作用是测量所有子 View 的宽高 接下来看 onlayout 先获取所有的子 View, 用 for 循环进行迭代, 调用 View 的 getmeasuredwidth 与 getmeasuredheight 方法获取子 View 的测量宽度和高度 注意, 这里不能调用 getwidth 和 getheight, 这两个方法必须在 onlayout 执行完才能调用, 不然返回都是 0 最后两行代码连起来看, 在 child.layout 这行代码中,layout 方法有 4 个参数, 分别是 Left Top Right Bottom, 分别表示当前 View 在 Viewgoup 中显示的位置 普及一下, 在 Android 手机上屏幕的左上角坐标是 [0,0], 测量之后给 left 加上当前 View 的宽度, 这样就能水平进行排列 然后看布局文件 activity_main.xml, 将布局换成了我们自己写的 MyViewGroup, 里面放了 3 个 TextView <com.ansen.views.myviewgroup xmlns:android=" android" android:layout_height="match_parent" android:background="@android:color/darker_gray"> <TextView android:layout_width="60dp" android:layout_height="60dp" android:background="@android:color/holo_red_light" android:padding="10dp" android:text="1"/> <TextView android:layout_width="60dp"

10 62 Android App 开发从入门到精通 android:layout_height="80dp" android:padding="10dp" android:text="2" /> <TextView android:layout_width="40dp" android:layout_height="60dp" android:padding="10dp" android:text="3" </com.ansen.views.myviewgroup> 运行代码, 效果如图 2-6 所示 图 2-6 自定义 ViewGroup 实现 LinearLayout 布局水平排列效果 提示 如果所有子 View 的宽度之和超过屏幕宽度, 就会显示非正常效果 这个案例主要以学习为 主 2. 测量 ViewGroup 宽高 如果我们把 activity_main.xml 文件中 MyViewGroup 控件的 android:layout_width 和 android:layout_height 属性的值改成 wrap_content, 就会发现 ViewGroup 的宽高还是填充整个屏幕, 所以需要重新修改 onmeasure 方法 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { // 获得此 ViewGroup 计算模式 int widthmode = MeasureSpec.getMode(widthMeasureSpec); int heightmode = MeasureSpec.getMode(heightMeasureSpec);

11 // 获取 ViewGroup 宽高 int sizewidth = MeasureSpec.getSize(widthMeasureSpec); int sizeheight = MeasureSpec.getSize(heightMeasureSpec); 第 2 章 Android 控件 63 measurechildren(widthmeasurespec,heightmeasurespec);// 测量所有子 View 的宽高 if(getchildcount()<=0){// 如果没有子 View 当前 ViewGroup 的宽高直接设置为 0 setmeasureddimension(0,0); else if(heightmode==measurespec.at_most&&widthmode== MeasureSpec.AT_MOST){ // 宽和高是 wrap_content int measuredwidth=0;// 测量宽度 int maxmeasuredheigh=0;// 测量高度子 View 最大的高度 for(int i=0;i<getchildcount();i++){ View child=getchildat(i); measuredwidth+=child.getmeasuredwidth(); if(child.getmeasuredheight()>maxmeasuredheigh){ // 如果当前的 View 大于之后 View 的高度 maxmeasuredheigh=child.getmeasuredheight(); setmeasureddimension(measuredwidth,maxmeasuredheigh); else{ setmeasureddimension(sizewidth,sizeheight); 首先获取 ViewGroup 计算模式, 如果宽和高都是 wrap_content, 迭代子 View, 所有子 View 的宽度加起来等于 ViewGroup 的宽度, 高度取子 View 中最高的值 重新运行代码, 效果如图 2-7 所示, 因为给 ViewGroup 设置了一个灰色的背景, 所以明显地看到 ViewGroup 的宽高正是我们想要的 图 2-7 ViewGroup 宽高根据子 View 来决定 3. 自定义 LayoutParams 我们在前面用 LinearLayout 布局时, 子 View 使用了 android:layout_weight 属性, 通过 layout_weight 属性来决定当前 View 在 LinearLayout 中的占比, 这也是因为 LinearLayout 源码中重写了 generatelayoutparams 方法 还有一种情况就是所有的控件都有 android:layout_margin 属性, 可以通过这个属性来设置控件之间的间距, 这是因为 ViewGroup 中封装了 MarginLayoutParams 静态类

12 64 Android App 开发从入门到精通 首先在 res/values 文件夹下新建 attrs.xml 文件, 自定义属性, 有两个值 right 和 bottom,right 让当前 View 显示在 ViewGroup 右边,bottom 让当前 View 显示在 ViewGroup 左边, 内容如下 : <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="customlayoutlp"> <attr name="layout_position"> <enum name="right" value="1" /> <enum name="bottom" value="2" /> </attr> </declare-styleable> </resources> 在 MyViewGroup 中新建静态内部类, 因为我们自定义的 ViewGroup 肯定也要设置子 View 之间的间距, 所以直接继承 MarginLayoutParams, 然后重写 generatelayoutparams 返回我们自己重写的 MyLayoutParams 在构造方法中把 layout_position 的值取出来赋值给 position 变量 public ViewGroup.LayoutParams generatelayoutparams(attributeset attrs){ return new MyLayoutParams(getContext(), attrs); public static class MyLayoutParams extends MarginLayoutParams { public static int POSITION_RIGHT = 1;// 右边 public static int POSITION_BOTTOM = 2;// 底部 public int position = -1;// public MyLayoutParams(Context c, AttributeSet attrs) { super(c, attrs); TypedArray a=c.obtainstyledattributes(attrs, R.styleable.CustomLayoutLP); position=a.getint(r.styleable.customlayoutlp_layout_position, position); a.recycle(); public MyLayoutParams(int width, int height) { super(width, height); public MyLayoutParams(ViewGroup.LayoutParams source) { super(source); LayoutParams 重写完了, 但是我们的 MyViewGroup 如果想要支持 android:layout_margin 属性以及自定义属性, 还得继续修改 onmeasure 和 onlayout 方法 onmeasure 方法只需要修改一行代码, 累加宽度的时候顺便加上左右边距 : MyLayoutParams lp= (MyLayoutParams) child.getlayoutparams(); measuredwidth+=child.getmeasuredwidth()+lp.leftmargin+lp.rightmargin;// 加上左右边距 onlayout 方法修改代码比较多, 修改后的代码如下 :

13 第 2 章 Android 控件 65 protected void onlayout(boolean changed, int l, int t, int r, int b) { Log.i("ansen","onLayout"); int count=getchildcount();// 获取子 View 数量 int left=0; for(int i=0;i<count;i++){ View child=getchildat(i); MyLayoutParams lp= (MyLayoutParams) child.getlayoutparams(); int childwidth=child.getmeasuredwidth();// 获取子 View 宽度 int childheight=child.getmeasuredheight();// 获取子 View 高度 if(lp.position==mylayoutparams.position_right){ // 当前子 View 显示在 ViewGroup 右边 child.layout(getwidth()-childwidth,0,getwidth(),childheight); // 设置摆放位置 else if(lp.position==mylayoutparams.position_bottom){ //// 当前子 View 显示在 ViewGroup 底部 child.layout(left+lp.leftmargin,getheight()-childheight,left+ childwidth+lp.leftmargin,getheight()); else{// 没有设置位置的 View child.layout(left+lp.leftmargin,0,left+childwidth+lp.leftmargin, child.getmeasuredheight()); Log.i("ansen","left:"+left+" top:"+0+" right:"+(left+childwidth)+" bottom:"+childheight); left+=childwidth+lp.leftmargin+lp.rightmargin; (1) 我们先看 position=-1 的 View, 也就是 else 里面的代码 这个有点绕, 要仔细地看几遍, 最好自己打印 log, 或者把 View 的宽高在纸上画出来 Top 和 Bottom 跟之前一样, 下面我们来看 Left 和 Right 当 i=0 的时候,Left= 左边距,Right= 宽度 + 左边距 当 i=1 的时候,Left= 上一个 View 到 ViewGroup 的宽度距离 + 上一个 View 的右边距 + 当前 View 的左边距,Right= 上一个 View 到 ViewGroup 的宽度距离 + 上一个 View 的右边距 + 当前 View 的宽度 + 当前 View 的左边距 (2) 接下来我们看 position 有值的 View, 只要理解了 position=-1 的情况,position=1 和 position=2 里面的代码就很好理解了 position=1 时, 当前 View 显示在 ViewGroup 的右边, 需要改变 onlayout 方法中的 Left 和 Right 参数, 既然是显示在 ViewGroup 的右边,Left 的值就是 ViewGroup 的宽度 - 当前 View 的宽度, Right 的值就是 ViewGroup 的宽度 position=2 时, 当前 View 显示在 ViewGroup 的底部, 需要改变 onlayout 方法中的 Top 和 Bottom, 原理同上

14 66 Android App 开发从入门到精通 最后重新修改 activity_main.xml 文件, 给控件设置外间距, 让第一个 TextView 显示在底部 最后一个 TextView 显示在右边 运行代码, 效果如图 2-8 所示 <com.ansen.views.myviewgroup xmlns:android=" xmlns:app=" <TextView android:layout_width="60dp" android:layout_height="60dp" android:padding="10dp" android:layout_marginleft="10dp" android:layout_marginright="10dp" app:layout_position="bottom" android:text="1"/> <TextView android:layout_width="60dp" android:layout_height="80dp" android:layout_marginleft="10dp" android:layout_marginright="20dp" android:padding="10dp" android:text="2" /> <TextView android:layout_width="40dp" android:layout_height="60dp" android:padding="10dp" app:layout_position="right" android:text="3" </com.ansen.views.myviewgroup> 图 2-8 ViewGroup 重写 generatelayoutparams 方法

15 第 2 章 Android 控件 67 第三个 TextView 设置了 right 但是却看不出效果, 需要修改一下 xml 文件, 把 MyViewGroup 控件的 android:layout_width 和 android:layout_height 改成 match_parent, 再次运行, 效果如图 2-9 所示 图 2-9 ViewGroup 重写 generatelayoutparams 方法 2.3 几种常用的布局 Android 中系统 SDK 有 5 种布局, 所有的布局都继承自 ViewGroup, 分别是 LinearLayout ( 线性布局 ) FrameLayout( 框架布局 ) AbsoluteLayout( 绝对布局 ) RelativeLayout( 相对布局 ) TableLayout( 表格布局 ) 但是从这几年的开发经验来看,AbsoluteLayout 与 TableLayout 几乎没有用到, 所以就给大家讲解其他三个常用布局 LinearLayout( 线性布局 ) LinearLayout 是线性布局控件, 是 ViewGroup 的子类, 会按照 android: orientation 属性的值对子 View 进行排序, 可以将子 View 设置为垂直或水平方向布局 LinearLayout 的每个子视图都会按照它们各自在 XML 中的出现顺序显示在屏幕上 其他两个属性 android:layout_width 和 android:layout_height 则是所有视图的必备属性, 用于指定它们的尺寸 1. 设置排列方式 android:orientation="vertical" ; 垂直排列 android:orientation="horizontal"; 水平排列 例如, 在 LinearLayout 布局中放三个 TextView 并且垂直显示, 布局如下 :

16 68 Android App 开发从入门到精通 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:text=" 文本 1"/> <TextView android:layout_margintop="10dp" android:layout_marginbottom="10dp" android:text=" 文本 2"/> <TextView android:text=" 文本 3"/> </LinearLayout> 垂直显示效果如图 2-10 所示, 让大家有一个直观感受, 其实就是从上往下一行一行显示 图 2-10 垂直显示 如果将排列方式改成 horizontal( 水平 ), 查看水平显示效果, 可以看到依次从左到右显示, 如图 2-11 所示 图 2-11 水平显示 2.android:layout_gravity( 对齐方式 ) layout_gravity 是 LinearLayout 子元素的特有属性 对于 layout_gravity, 该属性用于设置控件相对于容器的对齐方式, 可选项有 top bottom left right center_vertical center_horizontal center fill 等 接着上面的布局进行修改, 给 LinearLayout 中文本 2 设置一个 layout_gravity 属性 :

17 第 2 章 Android 控件 69 android:layout_gravity="center_horizontal" 其效果如图 2-12 所示 图 2-12 文本 2 设置 layout_gravity 属性从效果图中可以看到, 显示文本 2 的 TextView 水平居中了 3. weight( 权重 ) LinearLayout 布局中 layout_weight 属性用来分配子 View 在 LinearLayout 中占用的空间 ( 显示大小 ), 只有 LinearLayout 包裹的 View 才有这个属性 将上面水平显示的布局文件修改一下, 其效果如图 2-13 所示 图 2-13 三个 TextView 的宽度一致 从上面的效果图可以看出三个 TextView 的宽度是一致的 我们来看看源码有什么变化 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:background="@android:color/holo_red_light" android:layout_weight="1" android:text=" 文本 1"/> <TextView android:background="@android:color/holo_green_light" android:layout_weight="1" android:text=" 文本 2"/> <TextView

18 70 Android App 开发从入门到精通 android:layout_weight="1" android:text=" 文本 3"/> </LinearLayout> LinearLayout 的宽度匹配父类, 也就是屏幕的宽度, 然后来看三个 TextView 都设置了 android:layout_weight="1", 其实就是整个屏幕分成三份, 显示三个文本 因为怕大家不好区分, 所以顺便给 TextView 加上了背景颜色 在学习过程中大家也可以自己修改 android:layout_weight 的值, 看看会出现什么效果 例如, 把 1:1:1 改成 2:3:4, 当 android:layout_weight 的值改成 2:3:4 时, 通俗点解释就是把屏幕的宽度分成 9 份, 第一个 TextView 的宽度是 2/9, 第二个 TextView 的宽度是 3/9, 第三个 TextView 的宽度是 4/ RelativeLayout( 相对布局 ) RelativeLayout 是相对布局, 控件的位置是按照相对位置来计算的, 一个控件需要依赖另外一个控件或者依赖父控件 这是实际布局中最常用的布局方式之一 它灵活性大很多, 当然属性也多, 操作难度也大 RelativeLayout 常用的一些属性如下 : 第一类 : 属性值为 true 或 false android:layout_centerhorizontal 相对于父元素水平居中 android:layout_centervertical 相对于父元素垂直居中 android:layout_centerinparent 相对于父元素完全居中 ( 水平垂直都居中 ) android:layout_alignparentbottom 贴紧父元素的下边缘 android:layout_alignparentleft 贴紧父元素的左边缘 android:layout_alignparentright 贴紧父元素的右边缘 android:layout_alignparenttop 贴紧父元素的上边缘 第二类 : 属性值必须为 id 的引用名 "@+id/name" android:layout_below 在某元素的下方 android:layout_above 在某元素的上方 android:layout_toleftof 在某元素的左边 android:layout_torightof 在某元素的右边 android:layout_aligntop 本元素的上边缘和某元素的上边缘对齐 android:layout_alignleft 本元素的左边缘和某元素的左边缘对齐 android:layout_alignbottom 本元素的下边缘和某元素的下边缘对齐 android:layout_alignright 本元素的右边缘和某元素的右边缘对齐 第三类 : 属性值为具体的值, 如 30dp 40dp android:layout_marginbottom 离某元素底边缘的距离 android:layout_marginleft 离某元素左边缘的距离 android:layout_marginright 离某元素右边缘的距离 android:layout_margintop 离某元素上边缘的距离 由于涉及的属性比较多, 就不一一详细讲解了, 用 RelativeLayout 布局写了一个登录界面, 大家可以学习在布局中如何运用这些属性 <?xml version="1.0" encoding="utf-8"?>

19 第 2 章 Android 控件 71 <RelativeLayout xmlns:android=" android:layout_height="match_parent"> <TextView android:id="@+id/tv_nickname" android:layout_margintop="10dp" android:textsize="20sp" android:text=" 用户名 :" /> <EditText android:id="@+id/et_nickname" android:layout_torightof="@+id/tv_nickname" android:textsize="20sp" android:hint=" 请输入用户名 " /> <TextView android:id="@+id/tv_password" android:layout_margintop="20dp" android:layout_below="@+id/tv_nickname" android:layout_alignbottom="@+id/et_password" android:textsize="20sp" android:text=" 密码 :" /> <EditText android:id="@+id/et_password" android:layout_margintop="10dp" android:layout_below="@+id/tv_nickname" android:layout_torightof="@+id/tv_password" android:textsize="20sp" android:hint=" 请输入密码 " /> <Button android:layout_below="@+id/et_password" style="@style/widget.appcompat.button.colored" android:layout_alignparentright="true" android:text=" 登录 "/> </RelativeLayout> 从布局中可以看到, 通过 android:layout_torightof="@+id/tv_nickname" 属性把输入框放到文本的后面, 或者通过 android:layout_below="@+id/tv_nickname" 属性把密码输入框放到用户名的下面 还可以通过 android:layout_margintop 设置上面的外边距, 并为 Button 设置 android:layout_alignparentright="true" 属性, 就是放在父布局的右边 最后效果如图 2-14 所示

20 72 Android App 开发从入门到精通 图 2-14 RelativeLayout 效果 FrameLayout( 框架布局 ) FrameLayout 是 Android 中比较简单的布局之一, 该布局直接在屏幕上开辟出了一块空白区域 向其中添加控件时, 所有的组件都会置于这块区域的左上角 如果所有的组件都一样大的话, 同一时刻只能看到最上面的那个组件 当然, 可以为组件添加 layout_gravity 属性, 从而指定对齐方式 写一个简单的 Demo, 效果如图 2-15 所示 布局文件最外层是 FrameLayout 布局, 第一个控件是 TextView, 宽高都是 220dp, 第二个和第三个的宽高依次减少, 可以看到第三个会覆盖第二个, 第二个会覆盖第一个, 第四个 TextView 因为设置了 android:layout_gravity="center_horizontal bottom" 属性, 所以相对父布局水平居中并且位于底部 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android=" /android" android:layout_height="match_parent"> 图 2-15 FrameLayout 布局效果 <TextView android:layout_width="220dp" android:layout_height="220dp" android:background="@android:color/holo_red_light" /> <TextView android:layout_width="180dp" android:layout_height="180dp" android:background="@android:color/holo_blue_light" /> <TextView

21 第 2 章 Android 控件 73 android:layout_width="120dp" android:layout_height="120dp" android:background="@android:color/holo_orange_light"/> <TextView android:layout_width="50dp" android:layout_height="50dp" android:layout_gravity="center_horizontal bottom" android:background="@android:color/link_text_holo_dark"/> </FrameLayout> 三大布局嵌套以及动态添加 View 1. 多层嵌套当布局比较复杂时, 就需要多层嵌套来解决问题了, 但是也不要嵌套过多, 要灵活运用学会的这几种布局 当熟悉之后看到一个 Android 界面, 就知道哪里应该用什么布局 多层嵌套所有的布局都支持的,LinearLayout 嵌套 FrameLayout,FrameLayout 也可以嵌套 LinearLayout, 这里就用 LinearLayout 实现登录界面 先看效果, 如图 2-16 所示 图 2-16 嵌套效果 从宏观的角度来看, 第一行 第二行 第三行可以用 LinearLayout 的垂直排列实现, 接下来细分到每一行, 第一行与第二行用到了两个控件, 所以可以嵌套一层, 然后设置水平排列方式 第三行是一个按钮, 可以设置 android:layout_gravity="right" 属性 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:orientation="horizontal"> <TextView android:text=" 用户名 :"

22 74 Android App 开发从入门到精通 android:textsize="20sp" /> <EditText android:hint=" 请输入用户名 " android:textsize="20sp" /> </LinearLayout> <LinearLayout android:orientation="horizontal"> <TextView android:text=" 密码 :" android:textsize="20sp" /> <EditText android:hint=" 请输入密码 " android:textsize="20sp" /> </LinearLayout> <Button android:layout_gravity="right" android:text=" 登录 "/> </LinearLayout> 2. 动态添加 View 有时布局文件的 View 数量是不固定的, 需要根据逻辑来判断要添加多少 View 这种情况下, 只能在代码中来添加 View 了 我们就在登录的代码上增加 给 LinearLayout 设置一个 id, 这样才能在代码中查找这个控件 在布局中增加一个按钮 : <Button android:id="@+id/btn_add_view" style="@style/widget.appcompat.button.colored" android:layout_gravity="right" android:text=" 给 LinearLayout 动态添加 View"/>

23 第 2 章 Android 控件 75 Activity( 活动页面 ) 中的代码比较简单, 查找控件, 给按钮设置点击事件, 在点击回调中动态添加 View public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private LinearLayout llrootview; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); // 通过 id 查找 LinearLayout llrootview= (LinearLayout) findviewbyid(r.id.ll_root_view); // 给按钮设置点击事件 findviewbyid(r.id.btn_add_view).setonclicklistener(this); public void onclick(view v) { TextView textview=new TextView(this); textview.settext(" 动态添加 View"); llrootview.addview(textview);// 通过 addview 方法动态添加控件 运行修改后的代码, 其效果如图 2-17 所示 图 2-17 动态添加 View 2.4 初级控件的使用 本节将学习 Android 基础控件的使用, 了解常用属性并且熟练运用

24 76 Android App 开发从入门到精通 TextView( 文本视图 ) TextView 显示一行或者多行文本, 也能显示 html 在 Android 开发中,TextView 是最常用的组件之一, 基本上每天都会使用 1. 设置背景颜色 <TextView android:background="#ff00ff" android:layout_margintop="10dp" android:text=" 设置背景颜色 " /> 2. 在程序中动态赋值 这里既可以直接是字符串, 也可以是字符串资源 id TextView tv0=(textview) findviewbyid(r.id.tv0); tv0.settext(" 如何在程序里面动态赋值 "); 3. 实现多字符串的动态处理 (1) 在 strings.xml 文件中写上字符串 <string name="testing"> 这是一个数 :%1$d, 这是两位数 :%2$d, 这是三位数 :%3$s</string> (2) 在 Java 代码中设置值 tv1.settext(getstring(r.string.testing, new Integer[]{11,21,31)); 4. TextView 显示 html, 字体颜色为红色 需要注意的是, 不支持 html 标签的 style 属性 String html="<font color ='red'>textview 显示 html 字体颜色为红色 </font><br/>"; tv3.settext(html.fromhtml(html)); 5. 给 TextView 设置点击事件 这个事件是父类 View 的, 所以所有的 Android 控件都有这个事件, 这里为了方便就采用了内部类的方式 tv4.setonclicklistener(new OnClickListener() { public void onclick(view v) { Toast.makeText(MainActivity.this, " 点击了 TextView4", Toast.LENGTH_LONG).show(); ); 6. 给 TextView 文字加粗并设置阴影效果 字体阴影需要 4 个相关参数 : android:shadowcolor: 阴影的颜色 android:shadowdx: 水平方向上的偏移量

25 第 2 章 Android 控件 77 android:shadowdy: 垂直方向上的偏移量 android:shadowradius: 阴影的半径大小 <TextView android:id="@+id/tv5" android:layout_margintop="10dp" android:textstyle="bold" android:shadowcolor="#ff000000" android:shadowdx="10" android:shadowdy="10" android:shadowradius="1" android:text=" 文字阴影, 文字加粗 " /> 7. TextView 显示文字加图片 设置图片相关的属性主要有以下几个 : drawablebottom: 在文本框内文本的底端绘制指定图像 drawableleft: 在文本框内文本的左边绘制指定图像 drawableright: 在文本框内文本的右边绘制指定图像 drawabletop: 在文本框内文本的顶端绘制指定图像 drawablepadding: 设置文本框内文本与图像之间的间距 以下代码在文字左边显示一张图片, 并且设置文字跟图片之间的间距为 10dp <TextView android:id="@+id/tv6" android:layout_margintop="10dp" android:drawableleft="@drawable/ic_launcher" android:drawablepadding="10dp" android:gravity="center_vertical" android:text=" 文字 + 图片 " /> 8. TextView 的样式类 Span 的使用 首先新建一个 SpannableString 对象, 构造方法中传入要显示的内容, 调用 SpannableString 的 setspan 方法实现字符串各种风格的显示 setspan 方法有四个参数 参数 1 表示格式, 可以是前景色 背景色等, 我们这里用的是背景色 参数 2 设置格式的开始 index 参数 3 结束 index 参数 4 是一个常量, 有以下四个值 : Spannable. SPAN_INCLUSIVE_EXCLUSIVE: 前面包括, 后面不包括, 即在文本前插入新的文本会应用该样式, 而在文本后插入新文本不会应用该样式 Spannable. SPAN_INCLUSIVE_INCLUSIVE: 前面包括, 后面包括, 即在文本前插入新的文本会应用该样式, 而在文本后插入新文本也会应用该样式 Spannable. SPAN_EXCLUSIVE_EXCLUSIVE: 前面不包括, 后面不包括 Spannable. SPAN_EXCLUSIVE_INCLUSIVE: 前面不包括, 后面包括

26 78 Android App 开发从入门到精通 最后调用 TextView 的 settext 把 SpannableString 对象设置进去 SpannableString spannablestring = new SpannableString("TextView 的样式类 Span 的使用详解 ") ; BackgroundColorSpan backgroundcolorspan = new BackgroundColorSpan(Color.RED); //0 到 10 的字符设置红色背景 spannablestring.setspan(backgroundcolorspan, 0, 10, Spannable. SPAN_EXCLUSIVE_EXCLUSIVE) ; tv7.settext(spannablestring); 9. TextView 设置点击事件 Spannable 除了给 TextView 设置背景颜色之外, 还可以给 TextView 中某一段文字设置点击效果, 调用 SpannableString.setSpan 方法时第一次参数传入 ClickableSpan 格式 使用 ClickableSpan 时, 在点击链接时凡是有要执行的动作, 必须要给 TextView 设置 MovementMethod 对象 SpannableString spannableclickstring = new SpannableString("TextView 设置点击事件 Span") ; ClickableSpan clickablespan = new ClickableSpan() { public void onclick(view widget) { Toast.makeText(MainActivity.this,"TextView 设置点击事件 Span", Toast.LENGTH_LONG).show(); ; spannableclickstring.setspan(clickablespan,11,15, Spannable.SPAN_EXCLUSIVE_INCLUSIVE) ; tv8.setmovementmethod(linkmovementmethod.getinstance()); tv8.settext(spannableclickstring); 10. TextView 设置点击背景 新建一个 selector_textview.xml 文件, 放到 drawable 目录下 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android=" <item android:drawable="@color/textview_click_background" android:state_focused="true"/> <item android:drawable="@color/textview_click_background" android:state_pressed="true"/> <item android:drawable="@color/textview_default"/> </selector> 在 TextView 的 xml 布局中设置背景 android:background="@drawable/selector_textview" 设置点击事件 // 必须要给 TextView 加上点击事件, 点击之后才能改变背景颜色 findviewbyid(r.id.tv9).setonclicklistener(new OnClickListener() { public void onclick(view v) {

27 Toast.makeText(MainActivity.this," 点击了 TextView9", Toast.LENGTH_LONG).show(); ); 11. 跑马灯效果 第 2 章 Android 控件 79 当一行文本的内容太多, 导致无法全部显示, 也不想分行演示时, 可以让文本从左到右滚动显示, 类似于跑马灯 <!-- 跑马灯效果 --> <TextView android:id="@+id/tv12" android:layout_margin="10dp" android:ellipsize="marquee" android:marqueerepeatlimit="marquee_forever" android:scrollhorizontally="true" android:focusable="true" android:focusableintouchmode="true" android:singleline="true" android:text=" 跑马灯效果学好 android 开发就关注公众号 android 开发 666 经常推送原创文章 "/> 最后效果如图 2-18 所示 图 2-18 设置文本视图 Button( 按钮 ) Button 继承自 TextView 在 Android 开发中,Button 是常用的控件, 用起来很简单, 既可以写在 xml 布局文件中, 也可以在 Java 代码中手动创建后加入到布局管理器中, 其效果都是一样的 不过, 最好是在 xml 文档中定义, 因为一旦要改变界面的话, 直接修改 xml 就行了, 不用修改 Java 程序, 并且在 xml 中定义层次分明, 一目了然 Button 支持的 XML 属性及相关方法如表 2-2 所示

28 80 Android App 开发从入门到精通 表 2-2 Button 支持的 XML 属性及相关方法 XML 属性相关方法说明 android:clickable setclickable(boolean clickable) 设置是否允许点击 clickable=true: 允许点击 clickable=false: 禁止点击 android:background setbackgroundresource(int resid) 通过资源文件设置背景色 resid: 资源 xml 文件 ID 按钮默认背景为 android.r.drawable. btn_default android:text settext(charsequence text) 设置文字 android:textcolor settextcolor(int color) 设置文字颜色 android:onclick setonclicklistener(onclicklistener l) 设置点击事件 下面通过实例来给大家介绍 Button 的常用效果 首先看一下布局文件 activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:layout_height="match_parent" android:layout_marginleft="10dp" android:orientation="vertical"> <Button android:text="button 点击事件写法 1" /> <Button android:onclick="click" android:text="button 点击事件写法 2" /> <Button android:layout_margintop="10dp" android:padding="10dp" android:text="button 设置背景图片 " /> <Button android:layout_margintop="10dp" android:padding="10dp" android:text="button 设置背景颜色 " />

29 <Button android:layout_margintop="10dp" android:padding="10dp" android:text="button 设置 shape" /> <TextView android:layout_height="50dp" android:layout_marginleft="20dp" android:layout_marginright="20dp" android:layout_margintop="10dp" android:text="v7 包按钮样式 " android:textcolor="#ffffffff" android:textsize="20sp" /> </LinearLayout> 布局文件对应的效果如图 2-19 所示 第 2 章 Android 控件 81 图 2-19 布局了 6 个按钮 上面布局文件中定义了 6 个 Button, 指定的规则如下 (1) 按钮 1: 给 Button 指定了 android:id="@+id/btn_click_one", 在 MainActivity.xml 根据 id 进行查找并且设置点击事件 // 给第一个按钮设置点击事件 findviewbyid(r.id.btn_click_one).setonclicklistener(onclicklistener); 点击之后进行 Toast 提示 private View.OnClickListener onclicklistener=new View.OnClickListener() { public void onclick(view v){ Toast.makeText(MainActivity.this,"Button 点击事件 1", Toast.LENGTH_LONG).show();

30 82 Android App 开发从入门到精通 ; (2) 按钮 2: 给 xml 中的 button 增加了 android:onclick="click" 属性, 然后在该布局文件对应的 Acitivity 中实现该方法 需要注意的是, 这个方法必须符合三个条件 : 1 方法的修饰符是 public 2 返回值是 void 类型 3 只有一个参数 View, 这个 View 就是被点击的控件 public void click(view v){ switch (v.getid()){ case R.id.btn_click_two: Toast.makeText(MainActivity.this,"Button 点击事件 2", Toast.LENGTH_LONG).show(); break; (3) 按钮 3: 设置一张背景图片用 android:background 属性 android:background="@mipmap/icon_button_bg" (4) 按钮 4: 设置背景颜色用 android:background 属性 android:background="@android:color/holo_red_dark" (5) 按钮 5: 设置背景 shape,android:background="@drawable/shape_button_test", 可以自定义 Button 的外观, 从效果图中可以看到 Button 背景透明 有边框 有弧度 shape_button_test.xml 文件如下 : <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android=" > <!-- 默认背景色 --> <solid android:color="@android:color/transparent"/> <!-- 边框 --> <stroke android:width="1dp" android:color="@android:color/black" /> <!-- 设置弧度 --> <corners android:radius="20dp"/> </shape> (6) 按钮 6: 设置按钮的样式 style="@style/widget.appcompat.button.colored" 这是 V7 包中自带的 Style 样式 按钮的颜色是 ButtonTest/app/src/main/res/values/colors.xml 下 name="coloraccent" 的颜色 Button 使用注意事项 : (1)Button 的 setonclicklistener 优先级比 xml 中 android:onclick 高, 如果同时设置点击事件, 只有 setonclicklistener 才有效 (2) 能用 TextView 就尽量不要用 Button,TextView 灵活性更高

31 第 2 章 Android 控件 EditText( 文本编辑框 ) EditText 在开发中是经常用到的控件, 也是一个比较重要的组件, 可以说它是用户与 Android 应用进行数据传输的窗户, 比如实现一个登录界面, 需要用户输入账号和密码, 然后获取用户输入 的内容, 提交给服务器进行判断 EditText 支持的 XML 属性及相关方法如表 2-3 所示 表 2-3 EditText 支持的 XML 属性及相关方法 XML 属性 相关方法 说明 android:text settext(charsequence text) 设置文本内容 android:textcolor settextcolor(int color) 字体颜色 android:hint sethint(int resid) 内容为空时显示的文本 android:textcolorhint void sethinttextcolor(int color) 为空时显示的文本颜色 android:inputtype setinputtype(int type) 限制输入类型 number: 整数类型 numberdecimal: 小数点类型 date: 日期类型 text: 文本类型 ( 默认值 ) phone: 拨号键盘 textpassword: 密码 textvisiblepassword: 可见密码 texturi: 网址 android:maxlength 限制显示的文本长度, 超出部分不显示 android:minlines setmaxlines(int maxlines) 设置文本的最小行数 android:gravity setgravity(int gravity) 设置文本位置, 如设置成 center, 文本将居中显示 android:drawableleft setcompounddrawables(drawable 在 text 的左边输出一个 drawable, 如图片 left,drawable top,drawable right, Drawable bottom) android:drawablepadding 设置 text 与 drawable( 图片 ) 的间隔, 与 drawableleft drawableright drawabletop drawablebottom 一起使用, 可设置为负数, 单独使用没有效果 android:digits 设置允许输入哪些字符, 如 android:ellipsize 设置当文字过长时该控件该如何显示 start: 省略号显示在开头 end: 省略号显示在结尾 middle: 省略号显示在中间 marquee: 以跑马灯的方式显示 ( 动画横向移动 ) android:lines setlines(int lines) 设置文本的行数, 设置两行就显示两行, 即 使第二行没有数据

32 84 Android App 开发从入门到精通 ( 续表 ) XML 属性 相关方法 说明 android:linespacingextra 设置行间距 android:singleline setsingleline() true: 单行显示 false: 可以多行 android:textstyle 设置字形, 可以设置一个或多个, 用 "\ 1. EditText 实现登录界面 首先查看布局文件 activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/et_phone" android:layout_marginleft="20dp" android:layout_marginright="20dp" android:background="@null" android:inputtype="number" android:maxlength="11" android:hint=" 请输入手机号 " android:drawablepadding="10dp" android:padding="10dp" android:drawableleft="@mipmap/icon_phone" android:drawablebottom="@drawable/shape_et_bottom_line" android:layout_margintop="20dp"/> <EditText android:id="@+id/et_password" android:layout_marginleft="20dp" android:layout_marginright="20dp" android:layout_margintop="10dp" android:background="@null" android:inputtype="textpassword" android:maxlength="16" android:padding="10dp" android:drawablepadding="10dp" android:hint=" 请输入密码 " android:drawablebottom="@drawable/shape_et_bottom_line" android:drawableleft="@mipmap/icon_password"/> <TextView android:id="@+id/tv_login" style="@style/widget.appcompat.button.colored"

33 第 2 章 Android 控件 85 android:layout_height="50dp" android:layout_marginleft="10dp" android:layout_marginright="10dp" android:layout_margintop="30dp" android:text=" 登录 " android:textcolor="#ffffffff" android:textsize="18sp" /> </LinearLayout> 运行效果如图 2-20 所示 图 2-20 EditText 实现登录界面 这两个输入框用的大部分属性都在上面的表格中, 这里介绍一下没有提到的属性 android:background="@null" 表示输入框无背景 android:drawablebottom="@drawable/shape_et_ bottom_line" 表示底部引入一个 shape 布局文件, 这个布局文件就是输入框的下划线 shape_et_bottom_ line.xml 内容如下 : <shape xmlns:android=" android:shape="rectangle" > <solid android:color="#1e7ee3" /> <size android:height="1dp" android:width="500dp"/> </shape> 2. EditText 监听输入内容 当使用 Google 或者百度进行网页搜索时, 只要我们在输入框中输入内容, 就会对关键词进行联想匹配 实现的原理很简单, 就是监听输入框内容的变化, 把内容上传给服务器进行关键词查询, 然后客户端把结果展示出来 下面的代码实现了监听 EditText 内容的变化, 首先通过 id 找到 EditText 控件, 调用 EditText 控件的 addtextchangedlistener 添加文本改变监听, 这里我们用内部类方式实现 TextWatcher 接口, 重写 TextWatcher 接口的三个方法 (beforetextchanged ontextchanged aftertextchanged) 可以在 ontextchanged 方法中把用户输入的结果上传给服务器 EditText etone= (EditText) findviewbyid(r.id.et_phone); etone.addtextchangedlistener(new TextWatcher() {

34 86 Android App 开发从入门到精通 int after) { count) { ); public void beforetextchanged(charsequence s, int start, int count, Log.i("Ansen"," 内容改变之前调用 :"+s); public void ontextchanged(charsequence s, int start, int before, int Log.i("Ansen"," 内容改变, 可以去告诉服务器 :"+s); public void aftertextchanged(editable s) { Log.i("Ansen"," 内容改变之后调用 :"+s); ImageView( 图像视图 ) ImageView 用于显示图片的 View, 是开发中频繁使用的一个控件, 毕竟现在 4G 网络普及了, 手机加载一张图片很快, 所以很多 App 都使用了大量的图片 只需在 xml 文件加入 ImageView, 就能够显示图片 : <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_height="match_parent"> <ImageView android:id="@+id/iv_one" android:src="@mipmap/ic_launcher"/> </RelativeLayout> 这里给 ImageView 设置了 src 属性, 引用的图片在 mipmap 文件夹中, 是用 Android Studio 创建一个项目时自带的图片 在真实的企业开发中, 一般会替换掉这个图片的内容, 因为这张图片的名字一般用作程序的启动图标 程序运行效果如图 2-21 所示 图 2-21 添加图片 接下来, 给 ImageView 设置点击事件, 点击图片之后通过代码动态改变显示的图片 public class MainActivity extends AppCompatActivity {

35 第 2 章 Android 控件 87 private ImageView imageview; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); imageview=(imageview) findviewbyid(r.id.iv_one);// 通过 id 查找到图片控件 imageview.setonclicklistener(onclicklistener);// 设置点击监听事件 private View.OnClickListener onclicklistener=new View.OnClickListener() { public void onclick(view v) { imageview.setimageresource(r.mipmap.coffee);// 改变显示的图片 ; 在 oncreate 方法中, 首先通过 id 查找 xml 中的图片控件, 然后设置点击事件, 点击之后修改显示的图片, 其运行结果如图 2-22 所示 图 2-22 点击后显示新图片 可以看到点击之后图片改变了, 这张咖啡的图片是事先复制到 res/mipmap-hdpi 文件夹中的 RadioButton( 单选按钮 ) RadioButton 在 Android 开发中也是比较常见的控件, 从多个选项中选择一项时会用到 实现单选按钮需要将 RadioButton 和 RadioGroup 配合使用 RadioGroup 是单选组合框 ( 相当于容器 ), 用于将 RadioButton 框起来, 在没有 RadioGroup 的情况下,RadioButton 可以全部选中 ; 当多个 RadioButton 被 RadioGroup 包含的情况下,RadioButton 只可以选择一个 开发中比较常见的就是 App 注册界面需要选择性别, 一般都会有两个选项 : 男 / 女 首先查看布局文件, 就是外层一个 RadioGroup, 其中包含两个 RadioButton

36 88 Android App 开发从入门到精通 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_height="match_parent"> <RadioGroup android:orientation="horizontal"> <RadioButton android:text=" 男 "/> <RadioButton android:text=" 女 "/> </RadioGroup> </RelativeLayout> 布局文件只能展示 UI 效果, 但是我们的程序肯定要增加交互性, 需要把用户选中的结果记录下来, 所以还得在活动页面中监听 RadioGroup 的选中事件 public class MainActivity extends AppCompatActivity { protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); RadioGroup radiogroup= (RadioGroup) findviewbyid(r.id.radiogroup); radiogroup.setoncheckedchangelistener(oncheckedchangelistener); private OnCheckedChangeListener oncheckedchangelistener=new OnCheckedChangeListener() { public void oncheckedchanged(radiogroup group, int checkedid) { if(checkedid==r.id.rb_male){ Toast.makeText(MainActivity.this," 您的性别是男 ", Toast.LENGTH_SHORT).show(); else if(checkedid==r.id.rb_girl){ Toast.makeText(MainActivity.this," 您的性别是女 ", Toast.LENGTH_SHORT).show(); ;

37 第 2 章 Android 控件 89 在 oncreate 方法中通过 id 获取到 RadioGroup 对象, 然后将其设置为选中改变监听器, 在监听器的回调方法中通过 checkedid 来判断选中了哪个选项 接下来通过 Toast 进行显示 给大家补充一个新的知识点 :Toast 是 Android 中用来显示信息的一种机制, 与 Dialog 不一样的是,Toast 没有焦点, 而且 Toast 显示的时间有限, 会根据用户设置的显示时间后自动消失, 主要用于向用户显示提示信息 运行程序, 点击性别 男, 其效果如图 2-23 所示 Checkbox( 复选框 ) CheckBox 与 RadioButton 一样, 只有两种状态, 即选中与未选中, 两者的区别就是 CheckBox 可以实现多选 例如, 做一个在线考试系统, 选择题有单选题和多选题, 单选题可以用 RadioButton 实现, 多选题可以用 CheckBox 实现 上一节已经学习了 RadioButton, 接下来学习 CheckBox, 首先查看 xml 布局文件 : <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:text=" 你会几种编程语言?" /> <TextView android:id="@+id/tv_result" android:layout_margin="10dp" android:textsize="18sp" android:textcolor="@android:color/holo_blue_light"/> <CheckBox android:id="@+id/cb_java" android:text="java"/> <CheckBox android:id="@+id/cb_php" android:text="php"/> 图 2-23 单选按钮显示效果

38 90 Android App 开发从入门到精通 <CheckBox android:text="c"/> </LinearLayout> 前面用到了两个 TextView: 第一个用来显示提问的文字, 第二个用来展示选中之后的结果 后面是三个复选框, 代表三个选项 按照前面的例子, 大家应该明白了 xml 只有 UI 效果, 所有的逻辑需要在活动页面中处理 public class MainActivity extends AppCompatActivity { private TextView tvresult;// 用来显示结果 private String javaresult="",phpresult="",cresult=""; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); tvresult= (TextView) findviewbyid(r.id.tv_result); // 查找控件并且设置选中改变监听 CheckBox cbjava= (CheckBox) findviewbyid(r.id.cb_java); CheckBox cbphp= (CheckBox) findviewbyid(r.id.cb_php); CheckBox cbc= (CheckBox) findviewbyid(r.id.cb_c); cbjava.setoncheckedchangelistener(oncheckedchangelistener); cbphp.setoncheckedchangelistener(oncheckedchangelistener); cbc.setoncheckedchangelistener(oncheckedchangelistener); private CompoundButton.OnCheckedChangeListener oncheckedchangelistener=new CompoundButton.OnCheckedChangeListener() { public void oncheckedchanged(compoundbutton buttonview, boolean ischecked){ if(buttonview.getid()==r.id.cb_java){// 通过 id 区分不同的复选框 // 如果选中了 Java 就把 "Java" 赋值给 javaresult, 否则 "" 赋值给 javaresul // 这里用到了三元表达式, 如果不会请先去学习 java 基础 javaresult=ischecked?"java":""; else if(buttonview.getid()==r.id.cb_php){ phpresult=ischecked?"php":""; else if(buttonview.getid()==r.id.cb_c){ cresult=ischecked?"c":""; // 展示选中结果 tvresult.settext(javaresult+" "+phpresult+" "+cresult); ; 首先在 oncreate 中查找控件, 并设置选中改变监听, 在监听函数中根据 id 区分不同的复选框,

39 第 2 章 Android 控件 91 然后根据是否选中来赋值, 最后把结果给 TextView 显示在屏幕上 运行之后, 选中了 Java 和 C 复选框, 效果如图 2-24 所示 图 2-24 复选框显示效果 ProgressBar( 进度条 ) ProgressBar 在 Android 中比较常用 ProgressBar 分为确定的和不确定的两种, 确定的是能明确看到进度, 不确定的就是不清楚 不确定一个操作需要多长时间来完成 本例用了水平进度条和圆形进度条, 水平进度条是确定进度的, 圆形进度条表示不确定进度 同时在两个进度条的上方放上两个按钮, 用来操作水平进度条的进度值 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:orientation="horizontal"> <Button android:id="@+id/btn_add" android:text=" 进度值 +"/> <Button android:id="@+id/btn_reduce" android:text=" 进度值 -"/> </LinearLayout> <ProgressBar android:id="@+id/pb_horizontal"

40 92 Android App 开发从入门到精通 style="?android:attr/progressbarstylehorizontal" android:max="100" android:progress="0"/> <ProgressBar style="?android:attr/progressbarstylelarge" /> </LinearLayout> 这种逻辑代码与之前的差不多, 相信大家很熟悉了, 就是查找控件 接下来给两个按钮设置点击事件, 在点击回调方法中修改水平进度条的值 public class MainActivity extends AppCompatActivity { private ProgressBar pbhorizontal; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); pbhorizontal= (ProgressBar) findviewbyid(r.id.pb_horizontal); findviewbyid(r.id.btn_add).setonclicklistener(onclicklistener); findviewbyid(r.id.btn_reduce).setonclicklistener(onclicklistener); private View.OnClickListener onclicklistener=new View.OnClickListener() { public void onclick(view v) { switch (v.getid()){ case R.id.btn_add: pbhorizontal.setprogress(pbhorizontal.getprogress()+10); break; case R.id.btn_reduce: pbhorizontal.setprogress(pbhorizontal.getprogress()-10); break; ; 在真实的企业开发中, 一般用确定进度条表示下载文件进度, 用不明确的进度条表示正在访问网络 这里只是为了演示 ProgressBar 用法, 所以就用两个按钮的点击来修改进度条的值 最后运行效果如图 2-25 所示

41 第 2 章 Android 控件 93 图 2-25 两种不同的进度条 ProgressDialog( 进度对话框 ) ProgressDialog 经常用于一些费时的操作, 需要用户进行等待 例如, 加载网页内容, 这时需要一个提示来告诉用户程序正在运行, 并没有假死或者真死, 而 ProgressDialog 就是专门干这项工作的 一般使用它的步骤为 : 在执行耗时间的操作之前弹出 ProgressDialog 提示用户, 然后开一个新线程 在新线程中执行耗时的操作, 运行完毕之后通知主程序将 ProgressDialog 结束 新建项目, 首先修改 activity_main.xml 文件, 增加一个按钮, 布局文件比较简单, 就不贴出来了, 直接看 MainActivity 如何实现 : public class MainActivity extends AppCompatActivity { private ProgressDialog staticdialog; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); // 创建对象, 调用 Dialog 的 show 方法显示 //ProgressDialog dialog = new ProgressDialog(this); //dialog.setprogressstyle(progressdialog.style_horizontal);// 水平 //dialog.incrementprogressby(20);// 设置进度值 //dialog.setcanceledontouchoutside(false); // 设置在点击 Dialog 外是否取消 Dialog 进度条 // dialog.show();// 显示 // 调用 ProgressDialog 的静态方法显示 5 秒后关闭 模拟访问网络过程 findviewbyid(r.id.btn_show).setonclicklistener(new View.OnClickListener() { public void onclick(view v) { staticdialog = ProgressDialog.show(MainActivity.this," 这是标题 "," 这是内容 "); /* 开启一个新线程, 在新线程里执行耗时的方法 */

42 94 Android App 开发从入门到精通 new Thread(new Runnable() { public void run() { try { Thread.sleep(5000);// 延迟 5 秒 catch (InterruptedException e) { e.printstacktrace(); handler.sendemptymessage(0);// 延迟 5 秒之后发送消息给 handler ); ).start(); Handler handler = new Handler() { public void handlemessage(message msg){//handler 接收到消息后就会执行此方法 staticdialog.dismiss();// 关闭 ProgressDialog ; 调用 ProgressDialog 的静态方法显示, 开启一个新的线程, 延迟 5 秒, 然后给 handler 发送一个消息, 在 handler 的 handlemessage 方法中关闭 ProgressDialog 程序运行结果如图 2-26 所示 图 2-26 显示进度对话框 AlertDialog( 简单对话框 ) 在 Android 开发中, 经常需要在 Android 界面上弹出一些对话框, 例如询问用户或者让用户选择 ( 如删除提示对话框 警告对话框等 ), 这些功能用 AlertDialog 对话框来实现 public class MainActivity extends AppCompatActivity { protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate);

43 第 2 章 Android 控件 95 setcontentview(r.layout.activity_main); findviewbyid(r.id.btn_show_dialog).setonclicklistener(new View. OnClickListener() { public void onclick(view v) { showdialog(); ); // 显示对话框 protected void showdialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.settitle(" 提示 ");// 设置标题 builder.setmessage(" 确认退出吗?");// 设置消息 builder.seticon(r.mipmap.ic_launcher);// 设置 icon builder.setpositivebutton(" 确认 ",new DialogInterface.OnClickListener(){ public void onclick(dialoginterface dialog, int which) { dialog.dismiss(); MainActivity.this.finish();// 结束当前 Activity ); builder.setnegativebutton(" 取消 ",new DialogInterface.OnClickListener(){ public void onclick(dialoginterface dialog, int which) { dialog.dismiss(); ); builder.create().show(); 点击按钮, 弹出一个对话框, 给对话框设置了标题 内容 图片 两个按钮监听事件 这段代码相信大家很好理解, 运行效果图如图 2-27 所示 图 2-27 弹出简单对话框

44 96 Android App 开发从入门到精通 PopupWindow( 弹出式窗口 ) PopupWindow 弹出一个浮动的窗口, 可以显示在屏幕任意的位置, 比 Dialog 对话框更加灵活 ( 默认只能在屏幕的中间 ) 我们还可以通过 setanimationstyle 方法设置 PopupWindow 的显示或隐藏动画 本例中,PopupWindow 显示在某个控件之下 在 activity_main.xml 中放置两个按钮, 从上向下显示 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/btn_show_popupwindow" android:text=" 在当前位置下面弹出 PopupWindow" /> <Button android:id="@+id/btn_bottom_popupwindow" android:text=" 从底部弹出 PopupWindow" /> </LinearLayout> 在活动页面中根据 id 查找第一个按钮并且设置点击事件 : btnshowpopupwindow = (Button) findviewbyid(r.id.btn_show_popupwindow); btnshowpopupwindow.setonclicklistener(this); 在点击事件中调用 showasdropdown 方法 : public void onclick(view v) { if(v.getid()==r.id.btn_show_popupwindow){// 点击第一个按钮 showasdropdown(); 接下来, 通过 showasdropdown 方法显示 PopupWindow: private void showasdropdown(){ View popview = LayoutInflater.from(this).inflate(R.layout.popup_drop_down,null); // 设置 PopupWindow View, 宽度, 高度 PopupWindow popupwindow=new PopupWindow(popView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); // 设置允许在外点击消失, 必须要给 popupwindow 设置背景才会有效 popupwindow.setoutsidetouchable(true); popupwindow.setbackgrounddrawable(new BitmapDrawable());

45 第 2 章 Android 控件 97 // 显示在 btnshowpopupwindow 按钮下面,x 位置偏移 100px 就是偏移屏幕左边 100px popupwindow.showasdropdown(btnshowpopupwindow,100,0); PopupWindow 加载的布局文件 popup_drop_down.xml 如下 : <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:background="@color/coloraccent"> <TextView android:padding="10dp" android:text=" 我是点击上面那个按钮弹出的哦 " /> </LinearLayout> 运行以上代码, 其效果如图 2-28 所示 图 2-28 弹出式窗口 接下来的实例将 PopupWindow 显示在指定位置, 从下往上弹出 我们给第二个按钮设置点击事件, 调用 showbottompopupwindow 方法显示 PopupWindow 设置一个动画效果, 从下往上弹出 private void showbottompopupwindow(){ View popview = LayoutInflater.from(this).inflate(R.layout.popup_bottom,null); final PopupWindow popupwindow=new PopupWindow(popView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); popupwindow.setoutsidetouchable(true);// 设置允许在外点击消失 popupwindow.setbackgrounddrawable(new ColorDrawable(0x ));// 设置背景颜色 popupwindow.setanimationstyle(r.style.animation_bottom_dialog);// 设置动画 View.OnClickListener onclicklistener=new View.OnClickListener() { public void onclick(view v) { if(v.getid()==r.id.btn_camera_album){ Toast.makeText(MainActivity.this," 点击拍照按钮 ", Toast.LENGTH_SHORT).show(); else if(v.getid()==r.id.btn_camera_cancel){ Toast.makeText(MainActivity.this," 点击了取消按钮 ", Toast.LENGTH_SHORT).show();

46 98 Android App 开发从入门到精通 popupwindow.dismiss(); ; popview.findviewbyid(r.id.btn_camera_album).setonclicklistener (onclicklistener); popview.findviewbyid(r.id.btn_camera_cancel).setonclicklistener (onclicklistener); // 参数 1: 根视图, 整个 Window 界面的最顶层 View 参数 2: 显示位置 popupwindow.showatlocation(getwindow().getdecorview(),gravity.bottom,0,0); 底部 PopupWidnow 显示的布局文件 popup_bottom.xml 如下 : <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:padding="10dp" android:orientation="vertical"> <Button android:id="@+id/btn_camera_album" android:background="@color/coloraccent" android:text=" 拍照 " android:textsize="18sp" /> <Button android:id="@+id/btn_camera_cancel" android:layout_margintop="10dp" android:background="@color/colorprimarydark" android:text=" 取消 " android:textsize="18sp" /> </LinearLayout> 在上面的方法中, 还通过 setanimationstyle 方法设置了动画, 这是因为在 style.xml 中增加了一个 style,android:windowenteranimation 是 PopupWindow 显示动画,android:windowExitAnimation 是 PopupWindow 消失动画 <style name="animation_bottom_dialog"> <item name="android:windowenteranimation">@anim/bottom_dialog_enter</item> <item name="android:windowexitanimation">@anim/bottom_dialog_exit</item> </style> 在上面的 style 中引用了 res/anim 下的两个动画文件 bottom_dialog_enter.xml <?xml version="1.0" encoding="utf-8"?> <translate xmlns:android=" android:duration="225" android:fromydelta="100%"

47 第 2 章 Android 控件 99 android:interpolator="@android:anim/decelerate_interpolator" android:toydelta="0%"/> 解释上面这个 xml 中各个属性的作用 首先说明这是一个位置转移动画 android:duration: 动画的运行时间, 毫秒为单位 android:fromydelta: 动画起始时,Y 坐标上的位置 android:toydelta: 动画结束时,Y 坐标上的位置 android:interpolator: 用来修饰动画效果, 定义动画的变化率, 可以使动画效果 accelerated( 加速 ) decelerated( 减速 ) repeated( 重复 ) bounced( 弹跳 ) 等 bottom_dialog_exit.xml 中用的属性与上面的一样, 就不解释了 <?xml version="1.0" encoding="utf-8"?> <translate xmlns:android=" android:duration="225" android:fromydelta="0%" android:interpolator="@android:anim/accelerate_interpolator" android:toydelta="100%"/> 运行效果如图 2-29 所示, 显示与隐藏的动画效果无法截图, 大家自己运行源代码 DialogFragment DialogFragment 是在 Android 3.0 版本中被引入的, 是一种基于 Fragment 的 Dialog, 可以用来创建基本对话框 警告对话框, 以替代 Dialog 实现 DialogFragment, 需要重写 DialogFragment 并且实现 oncreateview(layoutinflater ViewGroup Bundle) 方法获取对话框显示内容, 或者重写 oncreatedialog(bundle) 来创建一个完全自定义的对话框 使用 DialogFragment 的好处如下 : 因为继承自 Fragment, 所以具有 Fragment 的所有特性, 可以更好地管理生命周期, 手机配置发生变化时, 我们能够进行监听 在活动页面中启动对话框, 要写一大堆逻辑代码 监听等, 但是通过 DialogFragment 控制对话框, 通过调用 API 来实现何时显示 隐藏 销毁, 就能够很方便地管理对话框 实例 : 重写 oncreateview 方法, 加载布局文件 继承 DialogFragment, 重写 oncreateview 方法 : public class MyDialogFragment extends DialogFragment { static MyDialogFragment newinstance() { return new MyDialogFragment(); 图 2-29 弹出式窗口

48 100 Android App 开发从入门到精通 public View oncreateview(layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) { View v = inflater.inflate(r.layout.hello_world, container, false); TextView tv = (TextView) v.findviewbyid(r.id.textview); tv.settext("this is an instance of MyDialogFragment"); return v; 在 oncreateview 方法中加载一个布局文件 hello_world.xml, 布局文件内容比较简单, 最外层是 FrameLayout, 里面是一个 TextView: <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android=" android:layout_height="match_parent"> <TextView android:id="@+id/textview" android:layout_height="match_parent" android:gravity="center" android:text="hello World" android:textsize="20sp"/> </FrameLayout> 这样就封装了一个 DialogFragment 对话框, 我们需要在哪个 activity 中使用就调用它显示一下, 一行代码即可轻松搞定 MyDialogFragment.newInstance().show(getSupportFragmentManager(),"MyDialogF ragment"); 运行代码, 效果如图 2-30 所示 图 2-30 DialogFragment 对话框

49 第 2 章 Android 控件 101 实例 : 重写 oncreateview 方法, 显示 AlertDialog 对话框 从如下代码中看到, 在 oncreatedialog 方法中创建了一个 AlertDialog 对象返回, 为对话框的两个按钮设置点击事件 因为要处理按钮的点击事件, 所以增加了 setonclicklistener 方法, 调用时可以注入对话框两个按钮点击事件监听的实现 public class MyAlertDialogFragment extends DialogFragment{ private DialogInterface.OnClickListener onclicklistener; public static MyAlertDialogFragment newinstance() { return new MyAlertDialogFragment(); public Dialog oncreatedialog(bundle savedinstancestate) { AlertDialog.Builder builder=new AlertDialog.Builder(getActivity()).setIcon(R.mipmap.ic_launcher).setTitle(R.string.app_name); if(onclicklistener!=null){// 设置对话框 ok&& 取消按钮的点击事件 builder.setpositivebutton(r.string.alert_dialog_ok,onclicklistener); builder.setnegativebutton(r.string.alert_dialog_cancel,onclicklistener); return builder.create(); public void setonclicklistener(dialoginterface.onclicklistener onclicklistener) { this.onclicklistener = onclicklistener; 通过以上代码, 我们可以看到设置点击监听就封装在自定义的 DialogFragment 中 接下来我们看如何在 Activity 中调用, 代码不多, 几行而已 MyAlertDialogFragment myalertdialogfragment=myalertdialogfragment.newinstance(); myalertdialogfragment.setonclicklistener(onclicklistener); myalertdialogfragment.show(getsupportfragmentmanager(),"myalertdialogfragm ent"); 点击对话框按钮时回调监听实现 : private DialogInterface.OnClickListener onclicklistener=new DialogInterface.OnClickListener() { public void onclick(dialoginterface dialog, int which) { switch (which){ case DialogInterface.BUTTON_POSITIVE://ok Log.i("ansen","ok"); break; case DialogInterface.BUTTON_NEGATIVE://cancel Log.i("ansen","cancel");

50 102 Android App 开发从入门到精通 ; break; 运行效果如图 2-31 所示 图 2-31 DialogFragment 对话框 2.5 Android 高级控件的使用 ListView( 列表视图 ) 在 Android 开发中,ListView 是很常用的控件, 以列表的形式展示具体内容, 并且能够根据数据的长度自适应显示 列表的显示需要三个元素 : ListVeiw: 用来展示列表的 View 适配器 : 用来把数据映射到 ListView 上的中介 数据源 :ListVeiw 中的每一行 View 对应数据源的一条数据 1. 简单使用 首先查看布局文件, 比较简单 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_height="match_parent"> <ListView android:id="@+id/listview" /> </RelativeLayout>

51 第 2 章 Android 控件 103 接下来查看代码, 先初始化数据, 循环 20 条数据放到一个集合中, 这个 items 集合就是数据源, 然后通过 id 获取 ListView 对象, 给 ListView 设置一个适配器 public class MainActivity extends AppCompatActivity { private ListView listview; private ListViewAdapter adapter; private List<String> items; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); initdata(); listview= (ListView) findviewbyid(r.id.listview); listview.setadapter(adapter=new ListViewAdapter(this,items)); // 初始化数据 private void initdata(){ items=new ArrayList<>(); for(int i=0;i<20;i++){ items.add("item:"+(i+1)); 自己写一个 ListViewAdapter 类, 继承 BaseAdapter, 然后重写 4 个方法 public class ListViewAdapter extends BaseAdapter{ private List<String> data; private LayoutInflater inflater; public ListViewAdapter(Context context,list<string> data){ inflater=layoutinflater.from(context); this.data=data; // 数据源长度 public int getcount() { return data.size(); // 每一行的绑定数据源 public Object getitem(int position) { return data.get(position); public long getitemid(int position) { return position;

52 104 Android App 开发从入门到精通 // 获取每一行的 View public View getview(int position, View convertview, ViewGroup parent) { ViewHolder viewholder; if(convertview==null){ viewholder=new ViewHolder(); //xml 文件加载成 View convertview = inflater.inflate(android.r.layout.simple_ list_item_1, parent, false); viewholder.text1= (TextView) convertview.findviewbyid (android.r.id.text1); convertview.settag(viewholder); else{ viewholder= (ViewHolder) convertview.gettag(); viewholder.text1.settext(data.get(position)); return convertview; private class ViewHolder{ private TextView text1; 对于上面的代码, 详细解释一下,ListView 在开始绘制时, 系统首先调用 getcount() 函数, 根据它的返回值得到 listview 的长度, 然后根据这个长度, 调用 getview() 逐一绘制每一行 如果 getcount() 返回值是 0, 列表将不显示 ; 如果返回值是 1, 就仅显示一行 这个适配器的写法是目前为止比较标准的固定写法,getView 方法中用到了 ViewHolder 类, 这是因为 ListView 有 RecycleBin 机制, 列表滚动时复用 ItemView, 这样做的好处就是, 不管列表滑动了几千条还是上万条的数据,ListView 滚动的过程中永远只会创建一屏的 View 如图 2-32 所示, 整个屏幕显示 12 条 View, 说明这个列表就算一直往下滚动, 也永远只会创建 12 个 View 2. 每一行点击监听 不需要给 ListView 每一行的 View 设置点击事件,ListView 源码已经封装了 setonitemclicklistener 方法 下面代码设置了 ListView 行点击事件, 点击之后显示一个 Toast 图 2-32 列表视图 listview.setonitemclicklistener(new AdapterView. OnItemClickListener(){ public void onitemclick(adapterview<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this," 点击 Item 位置 :"+position, Toast.LENGTH_SHORT).show(); );

53 第 2 章 Android 控件 设置分隔线 ListView 的每一行可以通过分隔线来区分, 只需要在布局中为 ListView 增加两个属性即可 android:divider="@android:color/holo_red_light" // 分隔线颜色 android:dividerheight="5dp" // 分隔线高度 添加了分隔线之后, 运行效果如图 2-33 所示 图 2-33 添加分隔线后的列表 如果不想要分隔线, 可以设置分隔线为空, 或者将分隔线颜色设为透明 : android:divider="@null" 或者 android:divider="@android:color/transparent" 4. 添加 header 和 footer 用 LayoutInflater 类的 from 静态方法获取一个 LayoutInflater 对象, 调用 inflate 方法将布局文件转化成 View, 给 View 设置一个点击监听, 调用 ListView 的 addheaderview 方法把头布局添加进去 View header=layoutinflater.from(this). inflate(r.layout.activity_listview_header,null); header.setonclicklistener(onclicklistener);// 给头布局设置一个点击事件 listview.addheaderview(header);// 添加头部 View View footer=layoutinflater.from(this). inflate(r.layout.activity_listview_footer,null); footer.setonclicklistener(onclicklistener);// 给头布局设置一个点击事件 listview.addfooterview(footer);// 添加尾部 View activity_listview_header.xml 文件比较简单, 就放置一个 TextView (activity_listview_footer 代码与此几乎一样, 就不贴出来了, 只是布局的 id 不一样而已, 用来判断点击事件 ) <?xml version="1.0" encoding="utf-8"?>

54 106 Android App 开发从入门到精通 <LinearLayout xmlns:android=" android:orientation="vertical"> <TextView android:gravity="center_horizontal" android:paddingtop="10dp" android:paddingbottom="10dp" android:text=" 这是 ListView 头部布局 " </LinearLayout> 在头 View 点击监听函数中就显示了一个 Toast, 大家对这样的代码应该很熟悉了 private View.OnClickListener onclicklistener=new View.OnClickListener() { public void onclick(view v) { switch (v.getid()){ case R.id.ll_header: Toast.makeText(MainActivity.this," 点击 ListView 头布局 ", Toast.LENGTH_SHORT).show(); break; ; 5. 动态修改 item 动态改变 ListView 很简单, 只需要修改数据源, 然后调用 adapter 的 notifydatasetchanged 方法更新适配器即可, 其他的底层已经封装好了 用代码来举个例子 : 点击尾部 View 为 ListView 添加一行数据 private View.OnClickListener onclicklistener=new View.OnClickListener() { public void onclick(view v) { switch (v.getid()){ case R.id.ll_footer:// 点击底部 items.add(" 点击底部添加的 item"); adapter.notifydatasetchanged(); break; ; 在底部点击监听方法中, 给数据源 ( 也就是集合 ) 添加一个字符串, 然后刷新适配器, 两行代码就能为 ListView 增加一行数据 如果想删除一行也是一样的, 删除源数据, 然后更新适配器 有兴趣的读者可以花点时间自己去实现

55 第 2 章 Android 控件 设置显示位置 listview.setselection(items.size()-1); // 显示列表最后一条运行结果如图 2-34 所示 7. 实现聊天界面一般情况下使用的 ListView 中每一行的 View 都是固定的, 但是一些特殊界面会有多个布局类型, 例如微信 陌陌 QQ 等聊天 App, 在聊天详情界面就有发送与接收两个布局, 其效果如图 2-35 所示 图 2-34 ListView 设置显示位置 图 2-35 聊天界面 想要实现图 2-35 中的效果, 需要给 Adapter 加载不同的 item 布局, 重写 Adapter 的 getviewtypecount 和 getitemviewtype 方法 //item 类型数量 public int getviewtypecount() { return TYPE_ACCEPT+1; // 每个类型对应的 int 类型的值必须从 0 开始 public int getitemviewtype(int position) { if(messages.get(position).issended()){ return TYPE_SEND;// 发送类型 return TYPE_ACCEPT;// 接收类型 为每种类型定义一个常量, 写在 ListViewAdapter 类中 private final int TYPE_SEND=0;// 消息发送

56 108 Android App 开发从入门到精通 private final int TYPE_ACCEPT=1;// 消息接收 当前, 在 getview 中也需要处理一下, 根据不同的类型加载不同的布局文件 public View getview(int position, View convertview, ViewGroup parent) { int type = getitemviewtype(position); Message message=messages.get(position); null); null); ViewHolder viewholder; if(convertview==null){ viewholder=new ViewHolder(); if(type==type_send){// 发送的消息 convertview = inflater.inflate(r.layout.item_message_chat_send, else if(type==type_accept){// 接收 convertview = inflater.inflate(r.layout.item_message_chat_accept, viewholder.tvcontent= (TextView) convertview.findviewbyid(r.id.tv_content); convertview.settag(viewholder); else{ viewholder= (ViewHolder) convertview.gettag(); viewholder.tvcontent.settext(message.getcontent()); return convertview; 发送布局文件与接收布局文件类似, 这里贴出一个发送的布局, 其中的内容比较简单, 仅一个 TextView 和 ImageView, 即内容与头像 不过, 控件的属性用得比较多 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:paddingbottom="7dip" android:paddingtop="7dip"> <TextView android:id="@+id/tv_content" android:layout_marginleft="55dp" android:layout_toleftof="@+id/iv_message_from_head_image" android:background="@mipmap/icon_message_from" android:gravity="center" android:paddingright="20dip" android:text=" 我已经吃过了 " android:textcolor="@color/white_normal" android:textsize="16dip" /> <!-- -->

57 <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_alignparentright="true" android:layout_marginleft="5dp" android:layout_marginright="5dp" /> </RelativeLayout> 第 2 章 Android 控件 109 如果仔细阅读了前面的内容, 就会发现每一行绑定的数据源不是 String 类型, 而是 Message 类型了 public class Message { private String content;// 消息内容 private boolean sended;// 是否发送 public Message(){ public Message(String content,boolean sended){ this.content=content; this.sended=sended; public String getcontent() { return content; public void setcontent(string content) { this.content = content; public boolean issended() { return sended; public void setsended(boolean sended) { this.sended = sended; 如果学会了以上内容,ListView 的基本使用就没问题了 这里在代码中加了注释, 并在代码后面做了详细的解释, 希望能够帮助大家更好地理解 GridView( 网格视图 ) GridView 是按照行列的方式来显示内容的, 一般用于显示图片列表, 比如九宫格列表, 使用 GridView 实现起来很简单 GridView 的用法与 ListView 类似, 首先看图 2-36, 效果图中显示的两张图片是网上找的

58 110 Android App 开发从入门到精通 图 2-36 网格视图 新建项目, 首先修改布局文件 activity_main.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_height="match_parent"> <GridView android:numcolumns="4" android:scrollbars="none" android:layout_marginbottom="10dp" android:verticalspacing="10dp" android:horizontalspacing="10dp" /> </RelativeLayout> GridView 控件中的几个属性作用如下 : android:numcolumns="4": 一行显示 4 列 android:scrollbars="none": 去掉滚动条 android:verticalspacing="10dp": 两行之间的间距 android:horizontalspacing="10dp": 两列之间的间距 Activity 的代码比较简单, 初始化数据 设置适配器 设置点击事件 public class MainActivity extends AppCompatActivity { private GridView gridview; private List<Integer> images; private GridAdapter gridadapter;

59 第 2 章 Android 控件 111 protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); initdata(); gridview= (GridView) findviewbyid(r.id.gridview); gridview.setadapter(gridadapter=new GridAdapter(this,images)); //item 设置点击事件 gridview.setonitemclicklistener(onitemclicklistener); private AdapterView.OnItemClickListener onitemclicklistener=new AdapterView.OnItemClickListener() { public void onitemclick(adapterview<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this," 当前选中了 " + ":"+position,toast.length_short).show(); ; // 初始化数据源 private void initdata(){ images=new ArrayList<>(); for(int i=0;i<100;i++){ if(i%2==1){// 对 2 取余数, 结果为 1 images.add(r.mipmap.test_one); else{ images.add(r.mipmap.test_two); GridView 适配器与 ListView 适配器类似,GridAdapter.java 代码如下 :( 因为类似所以代码不做详细解释 ) public class GridAdapter extends BaseAdapter{ private LayoutInflater inflater; private List<Integer> images; public GridAdapter(Context context,list<integer> images){ inflater=layoutinflater.from(context); this.images=images; public int getcount() { return images.size();

60 112 Android App 开发从入门到精通 public Object getitem(int position) { return images.get(position); public long getitemid(int position) { return position; public View getview(int position, View convertview, ViewGroup parent) { ViewHolder viewholder; if(convertview==null){ viewholder=new ViewHolder(); convertview = inflater.inflate(r.layout.activity_grid_item, parent, false); viewholder.imageview = (ImageView) convertview.findviewbyid (R.id.imageview); convertview.settag(viewholder); else{ viewholder= (ViewHolder) convertview.gettag(); viewholder.imageview.setimageresource(images.get(position)); return convertview; private class ViewHolder{ private ImageView imageview; item 的布局文件 :activity_grid_item.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:id="@+id/imageview" android:layout_gravity="center_horizontal" android:layout_height="70dp" android:scaletype="centercrop" android:src="@mipmap/test_one" /> </LinearLayout> android:scaletype="centercrop" 均衡地缩放图像 ( 保持图像原始比例 ), 使图片的宽高都大于等于 View 宽高 就本例而言,ImageView 的高度是 70dp, 宽度是包裹内容 ( 随内容多少而改变 ), 设置了这个属性之后, 图片会按照比例缩放到宽高都是 70dp 为止

61 第 2 章 Android 控件 RecyclerView( 循环视图 ) RecylerView 是 support-v7 包中的新组件, 是一个强大的滑动组件, 与经典的 ListView 相比, 同样拥有 item 回收复用的功能, 这一点从它的名字 RecylerView( 循环视图 ) 也可以看出 官方对于它的介绍是 :RecyclerView 是 ListView 的升级版本, 更加先进和灵活 RecyclerView 通过设置 LayoutManager ItemDecoration ItemAnimator 可实现更多效果 使用 LayoutManager 来确定每一个 item 的排列方式 使用 ItemDecoration 自己绘制分隔线, 更加灵活 使用 ItemAnimator 为增加或删除一行设置动画效果 注意 新建完项目, 需要在 app/build.gradle 增加 RecylerView 依赖, 不然找不到 RecyclerView 类 : compile 'com.android.support:recyclerview-v7:23.1.0' 1. RecylerView 简单的 Demo 我们来看 Activity 代码, 与 ListView 写法其实差不多, 这里只是多设置了一个布局管理器 public class LinearLayoutActivity extends AppCompatActivity { private RecyclerView recyclerview; private RecyclerViewAdapter adapter; private List<String> datas; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.recycler_main); initdata(); recyclerview= (RecyclerView) findviewbyid(r.id.recyclerview); recyclerview.setlayoutmanager(new LinearLayoutManager(this)); // 设置布局管理器 recyclerview.additemdecoration(new DividerItemDecoration(this)); recyclerview.setadapter(adapter=new RecyclerViewAdapter(this,datas)); private void initdata(){ datas=new ArrayList<>(); for(int i=0;i<100;i++){ datas.add("item:"+i); Activity 对应的布局文件 :recycler_main.xml 因为 RecyclerView 是 v7 包才有的控件, 所以需要在布局文件中指定包名 + 类名

62 114 Android App 开发从入门到精通 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_height="match_parent"> <android.support.v7.widget.recyclerview android:layout_height="match_parent"/> </RelativeLayout> Adapter 相对 ListView 的 Adapter 来说变化比较大 RecyclerViewAdapter.java 代码如下 : public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder>{ private List<String> datas; private LayoutInflater inflater; public RecyclerViewAdapter(Context context,list<string> datas){ inflater=layoutinflater.from(context); this.datas=datas; // 创建每一行的 View 用 RecyclerView.ViewHolder 包装 public RecyclerViewAdapter.MyViewHolder oncreateviewholder(viewgroup parent, int viewtype) { View itemview=inflater.inflate(r.layout.recycler_item,null); return new MyViewHolder(itemView); // 给每一行 View 填充数据 public void onbindviewholder(recyclerviewadapter.myviewholder holder, int position) { holder.textview.settext(datas.get(position)); // 数据源的数量 public int getitemcount() { return datas.size(); class MyViewHolder extends RecyclerView.ViewHolder{ private TextView textview; public MyViewHolder(View itemview) { super(itemview); textview= (TextView) itemview.findviewbyid(r.id.textview); 从上面的代码中看到需要继承 RecyclerView.Adapter, 重写三个方法 (oncreateviewholder

63 第 2 章 Android 控件 115 onbindviewholder getitemcount), 同时 MyViewHolder 也需要继承 RecyclerView.ViewHolder 运行代码, 效果如图 2-37 所示 2. RecyclerView 增加分隔线 图 2-37 RecyclerView RecyclerView 是没有 android:divider 与 android:dividerheight 属性的, 如果需要分隔线, 只能自己动手去实现 需要继承 ItemDecoration 类, 实现 ondraw 与 getitemoffsets 方法 调用 RecyclerView 的 additemdecoration 方法 先编写一个 DividerItemDecoration 类, 继承 RecyclerView.ItemDecoration, 在 getitemoffsets 留出 item 之间的间隔, 然后调用 ondraw 方法绘制 (ondraw 的绘制优先于每一行的绘制 ) public class DividerItemDecoration extends RecyclerView.ItemDecoration{ /* * RecyclerView 的布局方向, 默认先赋值为纵向布局 * RecyclerView 布局可横向, 也可纵向 * 横向和纵向对应的分隔线画法不一样 * */ private int morientation = LinearLayoutManager.VERTICAL; private int mitemsize = 1;//item 之间分隔线的 size, 默认为 1 private Paint mpaint;// 绘制 item 分隔线的画笔, 并设置其属性 public DividerItemDecoration(Context context) { this(context,linearlayoutmanager.vertical,r.color.coloraccent); public DividerItemDecoration(Context context, int orientation) {

64 116 Android App 开发从入门到精通 this(context,orientation, R.color.colorAccent); public DividerItemDecoration(Context context, int orientation, int dividercolor){ this(context,orientation,dividercolor,1); /** context orientation 绘制方向 dividercolor 分隔线颜色, 颜色资源 id mitemsize 分隔线宽度, 传入 dp 值就行 */ public DividerItemDecoration(Context context, int orientation, int dividercolor, int mitemsize){ this.morientation = orientation; if(orientation!= LinearLayoutManager.VERTICAL && orientation!= LinearLayoutManager.HORIZONTAL){ throw new IllegalArgumentException(" 请传入正确的参数 ") ; // 把 dp 值换算成 px this.mitemsize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_ UNIT_DIP,mItemSize,context.getResources().getDisplayMetrics()); mpaint = new Paint(Paint.ANTI_ALIAS_FLAG); mpaint.setcolor(context.getresources().getcolor(dividercolor)); public void ondraw(canvas c, RecyclerView parent, RecyclerView.State state) { if(morientation == LinearLayoutManager.VERTICAL){ drawvertical(c,parent) ; else { drawhorizontal(c,parent) ; /** * 绘制纵向 item 分隔线 canvas parent */ private void drawvertical(canvas canvas,recyclerview parent){ final int left = parent.getpaddingleft() ; final int right = parent.getmeasuredwidth() - parent.getpaddingright(); final int childsize = parent.getchildcount() ; for(int i = 0 ; i < childsize ; i ++){ final View child = parent.getchildat( i ) ; RecyclerView.LayoutParams layoutparams = (RecyclerView.LayoutParams) child.getlayoutparams(); final int top = child.getbottom() + layoutparams.bottommargin ; final int bottom = top + mitemsize ; canvas.drawrect(left,top,right,bottom,mpaint);

65 第 2 章 Android 控件 117 /** * 绘制横向 item 分隔线 canvas parent */ private void drawhorizontal(canvas canvas,recyclerview parent){ final int top = parent.getpaddingtop() ; final int bottom = parent.getmeasuredheight() - parent.getpaddingbottom() ; final int childsize = parent.getchildcount() ; for(int i = 0 ; i < childsize ; i ++){ final View child = parent.getchildat( i ) ; RecyclerView.LayoutParams layoutparams = (RecyclerView.LayoutParams) child.getlayoutparams(); final int left = child.getright() + layoutparams.rightmargin ; final int right = left + mitemsize ; canvas.drawrect(left,top,right,bottom,mpaint); /** * 设置 item 分隔线的 size outrect view parent state */ public void getitemoffsets(rect outrect, View view, RecyclerView parent, RecyclerView.State state) { if(morientation == LinearLayoutManager.VERTICAL){ outrect.set(0,0,0,mitemsize); // 垂直排列, 底部偏移 else { outrect.set(0,0,mitemsize,0); // 水平排列, 右边偏移 不要忘记调用 additemdecoration 方法哦! recyclerview.additemdecoration(new DividerItemDecoration(this));// 添加分隔线 重新运行, 效果如图 2-38 所示 大家读到这里肯定会有一个疑问, 这个比 ListView 麻烦多了, 但是 Google 官方为什么要说是 ListView 的升级版呢? 接下来开始放大招 图 2-38 添加分隔线

66 118 Android App 开发从入门到精通 3. GridLayoutManager 在 RecyclerView 中实现不同的列表, 只需切换不同的 LayoutManager( 布局管理器 ) 即可 RecyclerView.LayoutManager 与 RecyclerView.ItemDecoration 一样, 都是 RecyclerView 静态抽象内部类, 但是 LayoutManager 有三个官方写好的实现类 LinearLayoutManager( 线性布局管理器 ): 与 ListView 功能相似 GridLayoutManager( 网格布局管理器 ): 与 GridView 功能相似 StaggeredGridLayoutManager( 瀑布流布局管理器 ) 刚刚用的是 LinearLayoutManager, 现在切换到 GridLayoutManager 看到下面这句代码, 有没有感觉到很轻松呢? recyclerview.setlayoutmanager(new GridLayoutManager(this,2)); 如果要显示多列或者要纵向显示, 只需新建不同的构造方法即可 以下代码纵向显示 4 列 当然, 如果还需要反方向显示, 把 false 改成 true 即可 recyclerview.setlayoutmanager(new GridLayoutManager(this,4,GridLayoutManager.HORIZONTAL,false)); 因为用的是网格布局, 所以绘制分隔线的代码需要重新修改一下 网格布局一行可以有多列, 并且最后一列与最后一行不需要绘制, 所以需要重新创建一个类 :DividerGridItemDecoration.java public class DividerGridItemDecoration extends RecyclerView.ItemDecoration { /* * RecyclerView 的布局方向, 默认先赋值为纵向布局 * RecyclerView 的布局可横向, 也可纵向 * 横向和纵向对应的分隔线画法不一样 * */ private int morientation = LinearLayoutManager.VERTICAL; private int mitemsize = 1;//item 之间分隔线的 size, 默认为 1 private Paint mpaint;// 绘制 item 分隔线的画笔并设置其属性 public DividerGridItemDecoration(Context context) { this(context,linearlayoutmanager.vertical,r.color.coloraccent); public DividerGridItemDecoration(Context context, int orientation) { this(context,orientation, R.color.colorAccent); public DividerGridItemDecoration(Context context, int orientation, int dividercolor){ this(context,orientation,dividercolor,1); /** context orientation 绘制方向 dividercolor 分隔线颜色, 颜色资源 id mitemsize 分隔线宽度, 传入 dp 值就行

67 第 2 章 Android 控件 119 */ public DividerGridItemDecoration(Context context, int orientation, int dividercolor, int mitemsize){ this.morientation = orientation; if(orientation!= LinearLayoutManager.VERTICAL && orientation!= LinearLayoutManager.HORIZONTAL){ throw new IllegalArgumentException(" 请传入正确的参数 ") ; // 把 dp 值换算成 px this.mitemsize = (int) TypedValue.applyDimension(TypedValue. COMPLEX_UNIT_DIP, mitemsize,context.getresources().getdisplaymetrics()); mpaint = new Paint(Paint.ANTI_ALIAS_FLAG); mpaint.setcolor(context.getresources().getcolor(dividercolor)); public void ondraw(canvas c, RecyclerView parent, RecyclerView.State state) { drawhorizontal(c, parent); drawvertical(c, parent); private int getspancount(recyclerview parent) { // 列数 int spancount = -1; RecyclerView.LayoutManager layoutmanager = parent.getlayoutmanager(); if (layoutmanager instanceof GridLayoutManager) { spancount = ((GridLayoutManager) layoutmanager).getspancount(); else if (layoutmanager instanceof StaggeredGridLayoutManager) { spancount=((staggeredgridlayoutmanager)layoutmanager).getspancount(); return spancount; public void drawhorizontal(canvas canvas, RecyclerView parent) { int childcount = parent.getchildcount(); for (int i = 0; i < childcount; i++) { final View child = parent.getchildat(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getlayoutparams(); final int left = child.getleft() - params.leftmargin; final int right = child.getright() + params.rightmargin + mitemsize; final int top = child.getbottom() + params.bottommargin; final int bottom = top + mitemsize; canvas.drawrect(left,top,right,bottom,mpaint); public void drawvertical(canvas canvas, RecyclerView parent) { final int childcount = parent.getchildcount(); for (int i = 0; i < childcount; i++) { final View child = parent.getchildat(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getlayoutparams();

68 120 Android App 开发从入门到精通 final int top = child.gettop() - params.topmargin; final int bottom = child.getbottom() + params.bottommargin; final int left = child.getright() + params.rightmargin; final int right = left + mitemsize; canvas.drawrect(left,top,right,bottom,mpaint); public void getitemoffsets(rect outrect, int itemposition,recyclerview parent) { int spancount = getspancount(parent); int childcount = parent.getadapter().getitemcount(); if (islastrow(parent, itemposition, spancount, childcount)){ // 如果是最后一行, 不需要绘制底部 outrect.set(0, 0, mitemsize, 0); else if (islastcolum(parent, itemposition, spancount, childcount)){ // 如果是最后一列, 不需要绘制右边 outrect.set(0, 0, 0, mitemsize); else { outrect.set(0, 0, mitemsize,mitemsize); private boolean islastcolum(recyclerview parent, int pos, int spancount, int childcount) { RecyclerView.LayoutManager layoutmanager = parent.getlayoutmanager(); if (layoutmanager instanceof GridLayoutManager) { if ((pos + 1) % spancount == 0){// 如果是最后一列, 不需要绘制右边 return true; else if (layoutmanager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutmanager).getorientation(); if (orientation == StaggeredGridLayoutManager.VERTICAL) { if ((pos + 1) % spancount == 0){// 如果是最后一列, 不需要绘制右边 return true; else { childcount = childcount - childcount % spancount; if (pos >= childcount)// 如果是最后一列, 不需要绘制右边 return true; return false; private boolean islastrow(recyclerview parent, int pos, int spancount, int childcount) { RecyclerView.LayoutManager layoutmanager = parent.getlayoutmanager(); if (layoutmanager instanceof GridLayoutManager) { childcount = childcount - childcount % spancount; if (pos >= childcount)// 最后一行 return true;

69 第 2 章 Android 控件 121 else if (layoutmanager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutmanager). getorientation(); if (orientation == StaggeredGridLayoutManager.VERTICAL){// 纵向 childcount = childcount - childcount % spancount; if (pos >= childcount)// 最后一行 return true; else{ // 横向 if ((pos + 1) % spancount == 0) {// 最后一行 return true; return false; 写了这两个画分隔线的类和主流的布局, 线性列表与网格列表都能展示了 运行代码, 结果如图 2-39 所示 4. StaggeredGridLayoutManager 在 Activity 页面中修改布局管理器, 大家应该很熟悉了 recyclerview.setlayoutmanager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManag er.vertical)); 一般瀑布流列表的列高度是不一致的, 为了模拟不同的宽高, 把 String 类型改成对象, 然后初始化时随机一个高度即可 public class ItemData { private String content;//item 内容 private int height;//item 高度 图 2-39 线性列表与网格列表 public ItemData() { public ItemData(String content, int height) { this.content = content; this.height = height; public String getcontent() { return content; public void setcontent(string content) { this.content = content; public int getheight() { return height; public void setheight(int height) {

70 122 Android App 开发从入门到精通 this.height = height; 对应的适配器代码 StaggeredGridAdapter.java: public class StaggeredGridAdapter extends RecyclerView.Adapter<StaggeredGridAdapter.MyViewHolder>{ private List<ItemData> datas; private LayoutInflater inflater; public StaggeredGridAdapter(Context context, List<ItemData> datas){ inflater=layoutinflater.from(context); this.datas=datas; // 创建每一行的 View, 用 RecyclerView.ViewHolder 包装 public StaggeredGridAdapter.MyViewHolder oncreateviewholder(viewgroup parent, int viewtype) { View itemview=inflater.inflate(r.layout.recycler_staggered_item, parent,false); return new MyViewHolder(itemView); // 给每一行 View 填充数据 public void onbindviewholder(staggeredgridadapter.myviewholder holder, int position) { ItemData itemdata=datas.get(position); holder.textview.settext(itemdata.getcontent()); // 手动更改高度, 不同位置的高度有所不同 holder.textview.setheight(itemdata.getheight()); // 数据源的数量 public int getitemcount() { return datas.size(); class MyViewHolder extends RecyclerView.ViewHolder{ private TextView textview; public MyViewHolder(View itemview) { super(itemview); textview= (TextView) itemview.findviewbyid(r.id.textview); 需要注意的是, 我们在适配器的 onbindviewholder 方法中给 item 布局中的 TextView 设置了一个高度, 这个高度是创建实体类的时候随机生成的 item 对应的布局文件 :recycler_staggered_item.xml

71 第 2 章 Android 控件 123 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android=" android:padding="5dp" android:layout_height="match_parent"> <TextView android:id="@+id/textview" android:background="@color/coloraccent" android:layout_width="100dp" android:gravity="center" android:text="122" android:textsize="20sp"/> </FrameLayout> 瀑布流列表没有添加分割线, 为了展示效果, 给 item 布局设置了 android:padding 属性 是不是感觉很容易? 赶紧运行代码, 查看效果, 整个页面看起来变得生动活泼了, 如图 2-40 所示 5. 添加 header 和 footer 图 2-40 瀑布流效果 RecyclerView 添加头部与底部是没有对应的 api 的, 但是很多需求都会用到, 于是只能自己想办法实现了 可以通过适配器的 getitemviewtype 方法来实现这个功能 修改后的适配器代码 :RecyclerHeadFootViewAdapter.java public class RecyclerHeadFootViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ private List<String> datas; private LayoutInflater inflater; public static final int TYPE_HEADER=1;//header 类型 public static final int TYPE_FOOTER=2;//footer 类型 private View header=null;// 头 View

72 124 Android App 开发从入门到精通 private View footer=null;// 脚 View public RecyclerHeadFootViewAdapter(Context context, List<String> datas){ inflater=layoutinflater.from(context); this.datas=datas; // 创建每一行的 View, 用 RecyclerView.ViewHolder 包装 public RecyclerView.ViewHolder oncreateviewholder(viewgroup parent, int viewtype) { if(viewtype==type_header){ return new RecyclerView.ViewHolder(header){; else if(viewtype==type_footer){ return new RecyclerView.ViewHolder(footer){; View itemview=inflater.inflate(r.layout.recycler_item,null); return new MyViewHolder(itemView); // 给每一行 View 填充数据 public void onbindviewholder(recyclerview.viewholder holder, int position){ if(getitemviewtype(position)==type_header getitemviewtype(position) ==TYPE_FOOTER){ return; MyViewHolder myholder= (MyViewHolder) holder; myholder.textview.settext(datas.get(getrealposition(position))); // 如果有头部,position 的位置是从 1 开始的, 所以需要 -1 public int getrealposition(int position){ return header==null?position:position-1; // 数据源的数量 public int getitemcount() { if(header == null && footer == null){// 没有 head 跟 foot return datas.size(); else if(header == null && footer!= null){//head 为空 &&foot 不为空 return datas.size() + 1; else if (header!= null && footer == null){//head 不为空 &&foot 为空 return datas.size() + 1; else { return datas.size() + 2;//head 不为空 &&foot 不为空 public int getitemviewtype(int position){ // 如果头布局不为空 && 位置是第一个那就是 head 类型 if(header!=null&&position==0){

73 第 2 章 Android 控件 125 return TYPE_HEADER; else if(footer!=null&&position==getitemcount()-1){ // 如果 footer 不为空 && 最后一个 return TYPE_FOOTER; return super.getitemviewtype(position); public void setheader(view header) { this.header = header; notifyiteminserted(0);// 在位置 0 处插入一条数据, 然后刷新 public void setfooter(view footer) { this.footer = footer; notifyiteminserted(datas.size()-1);// 在尾部插入一条数据, 然后刷新 class MyViewHolder extends RecyclerView.ViewHolder{ private TextView textview; public MyViewHolder(View itemview) { super(itemview); textview= (TextView) itemview.findviewbyid(r.id.textview); getitemcount: 有 header 和 footer 时, 需要在源数据长度基础上进行增加 getitemviewtype: 通过 getitemviewtype 判断不同的类型 oncreateviewholder: 通过不同的类型创建 item 的 View onbindviewholder: 如果是 header 与 footer 类型是不需要绑定数据的,header 与 footer 的 View 一般在 Activity 页面中创建, 不需要处理, 所以这两种类型就不往下执行 如果有头布局, position==0 的位置就会被 header 占用, 但是数据源也就是集合的下标是从 0 开始的, 所以这里需要改为 -1 setheader: 设置头布局, 在第一行插入一条数据, 然后刷新 注意, 这个方法调用后会有插入的动画, 这个动画可以使用默认的, 也可以自己定义 setfooter: 设置尾部布局, 在尾部插入一条数据, 然后刷新 添加 header 与 footer 的方法终于封装好了, 在 Activity 页面中只需要两行代码就能添加 header, 与 ListView 调用 addheader 方法一样简单 这里需要注意的是, 初始化 View 时,inflate 方法需要三个参数 resource: 布局文件资源 id root: 父 View attachtoroot: 需要传入一个 boolean 类型的值 如果传入 true, 布局文件将转化为 View 并绑定到 root, 然后返回 root 作为根节点的整个 View 如果传入 false, 布局文件转化为 View 但不绑定到 root, 返回以布局文件根节点为根节点的 View

74 126 Android App 开发从入门到精通 // 添加 header View header=layoutinflater.from(this).inflate(r.layout.recycler_header, recyclerview,false); adapter.setheader(header); // 添加 footer View footer=layoutinflater.from(this).inflate(r.layout.recycler_footer, recyclerview,false); adapter.setfooter(footer); recycler_header 和 recycler_footer 布局文件只有一个 TextView, 直接看效果, 如图 2-41 所示 图 2-41 头布局与底部布局 6. item 点击事件 && 增加或删除带动画效果 当调用 RecyclerView 的 setonitemclicklistener 方法时, 发现居然没有该方法 用 RecyclerView 要习惯什么东西都自己封装 首先从 adapter 着手, 内部写一个接口 一个实例变量, 提供一个公共方法, 设置监听 private RecyclerViewItemClick recyclerviewitemclick; public void setrecyclerviewitemclick(recyclerviewitemclick recyclerviewitemclick) { this.recyclerviewitemclick = recyclerviewitemclick; public interface RecyclerViewItemClick{ /** * item 点击 realposition 数据源 position position view position */ void onitemclick(int realposition,int position); 在 onbindviewholder 方法中为 item 监听点击事件 : if(recyclerviewitemclick!=null) {

75 第 2 章 Android 控件 127 myholder.itemview.setonclicklistener(new View.OnClickListener() { public void onclick(view v) { recyclerviewitemclick.onitemclick(getrealposition(position), position); ); 在 Activity 页面的 oncreate 方法中进行监听, 顺便设置 item 增加或删除动画, 用的是 SDK 自带的默认动画 adapter.setrecyclerviewitemclick(recyclerviewitemclick); recyclerview.setitemanimator(new DefaultItemAnimator()); private RecyclerHeadFootViewAdapter.RecyclerViewItemClick recyclerviewitemclick=new RecyclerHeadFootViewAdapter.RecyclerViewItemClick() { public void onitemclick(int realposition, int position) { Log.i("ansen"," 删除数据 :"+realposition+" view 位置 :"+position); Log.i("ansen"," 当前位置 :"+position+" 更新 item 数量 : "+(adapter.getitemcount()-position-1)); ; datas.remove(realposition);// 删除数据源 adapter.notifyitemremoved(position);//item 移除动画 // 更新 position 至 adapter.getitemcount()-1 的数据 adapter.notifyitemrangechanged(position,adapter.getitemcount() -position-1); SwipeRefreshLayout( 下拉刷新 ) SwipeRefreshLayout 是一种下拉刷新控件, 在 Version 19.1 之后被放到 support v4 中, 继承自 ViewGroup SwipeRefreshLayout 控件只允许有一个子元素, 子元素一般是 ListView 或者 RecyclerView 1. SwipeRefreshLayou 下拉刷新 上一节学习了 RecyclerView, 这里就在 RecyclerView 简单 Demo 的基础上加上下拉刷新 首先看布局文件 activity_main.xml, 把最外层的布局控件换成 SwipeRefreshLayout <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.swiperefreshlayout xmlns:android=" android:id="@+id/swiperefreshlayout" android:layout_height="match_parent"> <RecyclerView android:id="@+id/recyclerview" android:layout_height="match_parent"/> </android.support.v4.widget.swiperefreshlayout>

76 128 Android App 开发从入门到精通 接下来, 在 Activity 页面中设置刷新监听, 设置刷新箭头的颜色 : t; swiperefreshlayout=(swiperefreshlayout)findviewbyid(r.id.swiperefreshlayou // 监听刷新状态 swiperefreshlayout.setonrefreshlistener(this); // 设置下拉刷新的箭头颜色 ( 可以设置多个颜色 ) swiperefreshlayout.setcolorschemeresources(r.color.coloraccent, android.r.color.holo_green_light,r.color.colorprimary); 刷新监听回调方法, 这里为了模拟访问网络请求, 用 Handle 来达到延时的效果 有关 Handle 的使用方法, 后续的章节会详细介绍 public void onrefresh() { // 延迟 3000 毫秒, 发送空消息跟 handle,handle 的 handlemessage 方法会接收到 handler.sendemptymessagedelayed(pull_to_refresh,3000); PULL_TO_REFRESH 是一个常量, 在 Activity 中定义如下 : public static final int PULL_TO_REFRESH=1;// 下拉刷新 下面来看 Handle 是怎么实现的, 可以通过 msg 对象的 what 来判断是什么消息 private Handler handler=new Handler(){ public void handlemessage(message msg) { switch (msg.what){ case PULL_TO_REFRESH:// 下拉刷新 if(datas.size()>0){ datas.remove(0);// 删除第一条 adapter.notifydatasetchanged();// 更新第一条记录 swiperefreshlayout.setrefreshing(false); //false, 刷新完成 ;true, 正在刷新 break; ; 通过上面为数不多的代码, 就实现了 RecyclerView 下拉刷新的效果 运行代码, 正在刷新中的效果如图 2-42 所示

77 第 2 章 Android 控件 129 图 2-42 正在刷新中 2. RecyclerView 加载更多 既然有了下拉刷新功能, 肯定还需要加载更多, 在 SwipeRefreshLayout 控件的 api 中并没有这个功能, 只能从 RecyclerView 入手 首先修改 item 布局文件 recycler_item.xml, 增加 ProgressBar 进度条 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:orientation="vertical"> <TextView android:id="@+id/textview" android:padding="10dp" android:text="122" android:textsize="20sp"/> <ProgressBar android:id="@+id/progressbar" style="@style/widget.appcompat.progressbar" android:layout_gravity="center_horizontal" android:padding="3dp" /> </LinearLayout> 在 adapter 内部类 MyViewHolder 中查找这个控件 : class MyViewHolder extends RecyclerView.ViewHolder{ private TextView textview;

78 130 Android App 开发从入门到精通 private ProgressBar progressbar; public MyViewHolder(View itemview) { super(itemview); textview= (TextView) itemview.findviewbyid(r.id.textview); progressbar= (ProgressBar) itemview.findviewbyid(r.id.progressbar); 在 adapter 中的 onbindviewholder 方法增加以下代码 :( 如果列表有 5 条记录并且是最后一条记录, 将显示进度条, 否则隐藏进度条 ) if(position>5 && position == datas.size()-1){ holder.progressbar.setvisibility(view.visible); else{ holder.progressbar.setvisibility(view.gone); 在 Activity 页面中监听 recyclerview 滚动 : recyclerview.addonscrolllistener(onscrolllistener); 下面用一个实例变量控制加载状态 : private RecyclerView.OnScrollListener onscrolllistener=new RecyclerView.OnScrollListener() { public void onscrolled(recyclerview recyclerview, int dx, int dy) { super.onscrolled(recyclerview, dx, dy); RecyclerView.LayoutManager mlayoutmanager = recyclerview. getlayoutmanager(); int lastvisibleitem = ((LinearLayoutManager) mlayoutmanager). findlastvisibleitemposition(); int totalitemcount = mlayoutmanager.getitemcount(); // 最后一项显示 && 下滑状态的时候回调加载更多 if (lastvisibleitem >= totalitemcount-1 && dy > 0) { if(!isloadmore){ loadmore();// 加载更多 isloadmore=true; ; 加载更多的方法, 模拟访问网络延迟 1000 毫秒给 handle 发送一个消息 : public void loadmore() { handler.sendemptymessagedelayed(up_to_refresh,1000); 为在 handle 中判断 what 的 switch 增加一个 case, 这里要加载更多, 为列表增加三行数据 在企业开发中, 基本都是请求下一页数据, 然后更新列表 case UP_TO_REFRESH:// 上拉加载更多 for(int i=0;i<3;i++){ datas.add("load more item:"+i);

79 第 2 章 Android 控件 131 adapter.notifydatasetchanged();// 更新列表 isloadmore=false;// 加载更多完成 break; 因为书中能展示的代码有限, 所以都是展示要修改的代码, 如果大家看起来有困难, 可以对照源代码学习 运行代码, 有一个波纹效果, 这是 5.0 操作系统自带的, 如图 2-43 所示 图 2-43 RecyclerView 的效果 ViewPager( 翻页视图 ) ViewPager 是 Android 扩展包 v4 中的类, 可以让用户左右切换 View ViewPager 的用法与 ListView 类似, 需要设置 PagerAdapter 来完成页面和数据的绑定, 这个 PagerAdapter 是一个基类适配器, 经常用来实现 App 引导图 它的子类有 FragmentPagerAdapter 和 FragmentStatePagerAdapter, 和 Fragment 一起使用 在 Android 应用中, 它们就像 ListView 一样出现得较频繁 本节实例将用 ViewPager 来实现 Fragment 的滑动 首先看布局文件 activity_main.xml, 外层是 RelativeLayout, 里面包含一个 ViewPager 控件 : <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_height="match_parent"> <android.support.v4.view.viewpager android:id="@+id/viewpager" android:layout_height="match_parent"/> </RelativeLayout> 接下来看布局文件对应的 Activity 如何实现, 首先查找 Viewpager 控件, 设置缓存页数, 设置当前显示第几个 Fragment, 然后初始化 FragmentAdapter 适配器, 这个适配器是我们自己写的, 集

80 132 Android App 开发从入门到精通 成自 FragmentStatePagerAdapter, 接下来调用适配器的 addfragment 方法将要显示的 Fragment 添加进去 最后调用 ViewPager 的 setadapter 方法将适配器设置进去 当想知道 ViewPager 滑动到哪个 Fragment 时, 可以通过 addonpagechangelistener 方法来设置监听 public class MainActivity extends AppCompatActivity { protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); ViewPager vpager = (ViewPager) findviewbyid(r.id.viewpager); vpager.setoffscreenpagelimit(2);// 设置缓存页数 vpager.setcurrentitem(0);// 设置当前显示的 item 0 表示显示第一个 FragmentAdapter pageradapter = new FragmentAdapter (getsupportfragmentmanager()); pageradapter.addfragment(new FragmentTest(" 页面 1",android.R.color. holo_red_dark)); pageradapter.addfragment(new FragmentTest(" 页面 2",android.R.color. holo_green_dark)); pageradapter.addfragment(new FragmentTest(" 页面 3",android.R.color. holo_red_dark)); pageradapter.addfragment(new FragmentTest(" 页面 4",android.R.color. holo_green_dark)); // 给 ViewPager 设置适配器 vpager.setadapter(pageradapter); // 页面改变监听 vpager.addonpagechangelistener(onpagechangelistener); private ViewPager.OnPageChangeListener onpagechangelistener=new ViewPager. OnPageChangeListener() { // 页面滑动 public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) { // 页面选择 public void onpageselected(int position) { Log.i("MainActivity"," 选中了页面 "+(position+1)); ; // 页面滑动状态改变 public void onpagescrollstatechanged(int state) { FragmentAdapter.java 继承 FragmentStatePagerAdapter 类, 与 BaseAdapter 有点类似 相对于 BaseAdapter 适配器,FragmentStatePagerAdapter 不需要重写 getview 方法

81 第 2 章 Android 控件 133 public class FragmentAdapter extends FragmentStatePagerAdapter { private final List<Fragment> fragmentlist = new ArrayList<Fragment>(); public FragmentAdapter(FragmentManager fm) { super(fm); public Fragment getitem(int arg0) { return fragmentlist.get(arg0); public int getcount() { return fragmentlist.size(); public void addfragment(fragment fragment) { fragmentlist.add(fragment); FragmentTest.xml 在构造方法中传入两个参数, 参数 1 是内容, 参数 2 是页面背景颜色 fragment_test.xml 只有一个 TextView, 非常简单, public class FragmentTest extends Fragment { private String content; private int backgroundresourceid; public FragmentTest(String content,int backgroundresourceid){ this.content=content; this.backgroundresourceid=backgroundresourceid; public View oncreateview(layoutinflater inflater, ViewGroup container, Bundle savedinstancestate){ View rootview=layoutinflater.from(getactivity()).inflate(r.layout. fragment_test, null); TextView tvcontent= (TextView) rootview.findviewbyid (R.id.tv_content); tvcontent.settext(content); rootview.setbackgroundresource(backgroundresourceid); return rootview; 效果如图 2-44 所示 这是 ViewPager 滑动到一半的截图, 页面一和页面二都显示一半

82 134 Android App 开发从入门到精通 图 2-44 翻页视图 2.6 通过 xml 文件修饰 View shapes( 设置圆角 边框 填充色 渐变色 ) shape 用来控制控件 (View) 的几何形状, 有 6 个子标签 : corners: 圆角 solid: 填充颜色 stroke: 描边 padding: 内边距 size: 宽高 gradient: 渐变 在 res/drawable 目录下新建一个文件 tv_shape.xml: <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android=" <!-- 圆角 --> <corners android:radius="10dp"/> <!-- 填充颜色 --> <solid android:color="@android:color/white"/> <!-- 描边 --> <stroke android:width="5dp" android:color="@color/coloraccent" /> <!-- 内边距 --> <padding android:top="10dp" android:bottom="10dp" android:left="10dp"

83 第 2 章 Android 控件 135 android:right="10dp"/> </shape> 在布局文件中为 TextView 设置 background, 引用刚刚写的 shape <TextView android:background="@drawable/tv_shape" android:text="hello World!" /> 效果如图 2-45 所示 图 2-45 设置圆角图形 因为渐变色和填充色不能同时使用, 所以接着为渐变色新建一个 shape 文件 tv_shape_two.xml, 顺便增加一个 size 标签, 指定该 View 的宽高都是 100dp <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android=" <!-- 宽高 --> <size android:width="100dp" android:height="100dp" /> <!-- 渐变 --> <gradient android:endcolor="#ff8c00" android:gradientradius="50" android:startcolor="#ffffff" android:type="linear" /> </shape> 解释上面的渐变标签,android:startColor 和 android:endcolor 分别为起始和结束颜色, android:angle 是渐变角度, 必须为 45 的整数倍 另外, 渐变默认的模式为 android:type="linear", 即线性渐变 可以指定渐变为径向渐变, android:type="radial", 径向渐变需要指定半径 android:gradientradius="50" 效果如图 2-46 所示 图 2-46 渐变效果

84 136 Android App 开发从入门到精通 selector( 设置点击 选中点击效果 ) 当用户点击界面的某个按钮或者图片的时候, 需要告诉用户 : 你的点击我收到了 例如, 大部分 App 注册时需要选择用户性别, 都可能会用到 selector 下面介绍 selector 标签中 item 标签的常用属性 1. android:state_pressed 属性 在 drawable 目录下新建一个 selector_button_pressed.xml 文件 : <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android=" <!-- 按下背景颜色 --> <item android:drawable="@color/coloraccent" android:state_pressed="true"/> <!-- 默认背景颜色 --> <item android:drawable="@color/colorprimary"/> </selector> 给按钮设置一个背景颜色 : android:background="@drawable/selector_button_pressed" 左边是默认效果, 右边是按下效果, 如图 2-47 所示 2. android:state_checked 图 2-47 为按钮设置背景颜色 一般 Checkbox( 复选框 ) 使用这个属性比较多 在 drawable 目录下新建一个 selector_check_state. xml 文件, 用 android:drawable 引用图片, 是之前准备好的两张图片, 表示勾选状态和未勾选状态 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android=" <!-- 选中时显示图片 --> <item android:drawable="@mipmap/icon_checkbox_selector" android:state_checked="true" /> <!-- 未选中时显示图片 --> <item android:drawable="@mipmap/icon_checkbox_normal" android:state_checked="false" /> </selector> 用 Checkbox 控件的 android:button 引用这个文件 : <CheckBox android:layout_margintop="20dp" android:button="@drawable/selector_check_state"/> 未勾选状态跟勾选状态的效果如图 2-48 所示

85 第 2 章 Android 控件 137 图 2-48 复选框的两种状态 3. android:state_selected 选中状态和未选中状态其实与 android:state_checked 类似 这个属性大部分控件都能使用, 一般需要自己在代码中设置选中和未选中状态 新建一个文件 selector_imageview.xml, 引用的图片与上一个属性图片一样 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android=" <!-- 选中时显示图片 --> <item android:drawable="@mipmap/icon_checkbox_selector" android:state_selected="true" /> <!-- 未选中时显示图片 --> <item android:drawable="@mipmap/icon_checkbox_normal" android:state_selected="false" /> </selector> 给 ImageView 控件设置 android:background: android:background="@drawable/selector_imageview" 在 MainActivity 中设置 ImageView 点击事件, 在点击事件设置选中状态 public void onclick(view v) { // 获取状态, 取反, 设置取反后的状态 imageview.setselected(!imageview.isselected()); 效果图和 CheckBox 的勾选效果一样, 只不过用的控件以及 selector 的属性不一样, 如图 2-49 所示 图 2-49 复选框的两种状态 layer-list( 把 item 按照顺序层叠显示 ) 使用 layer-list 可以将多个 drawable 按照顺序层叠在一起显示 最先定义的在最下方显示, 后面的依次往上叠放

86 138 Android App 开发从入门到精通 在 drawable 目录下新建 layer_list_textview.xml 文件 : <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android=" <item > <shape android:shape="rectangle" > <solid android:color="#0000ff"/> </shape> </item> <item android:bottom="25dp" android:top="25dp" android:left="25dp" android:right="25dp"> <shape android:shape="rectangle" > <solid android:color="#00ff00"/> </shape> </item> <item android:bottom="50dp" android:top="50dp" android:left="50dp" android:right="50dp"> <shape android:shape="rectangle" > <solid android:color="#ff0000" /> </shape> </item> </layer-list> 为 TextView 设置 background 属性引用这个文件, 并且设置 padding 属性 <TextView android:background="@drawable/layer_list_textview" android:padding="50dp" android:text="hello World!"/> 如图 2-50 所示, 蓝色在最底部 ( 定义的第一个 item), 红色在最上面 ( 定义的最后一个 item) 图 2-50 layer-list 的使用 2.7 本章小结 现在市场上的应用程序五花八门, 每一个类型都有几十个应用程序相互竞争, 熟练使用控件才能做出更好的 App 本章主要介绍了使用较多的三种布局以及控件的使用, 每个控件都提供了案例, 让读者加深对组件的理解 通过本章的学习, 相信大家在开发过程中也能灵活应用, 在不同的 UI 界面上知道应该使用哪种控件最合适

res/layout 目录下的 main.xml 源码 : <?xml version="1.0" encoding="utf 8"?> <TabHost android:layout_height="fill_parent" xml

res/layout 目录下的 main.xml 源码 : <?xml version=1.0 encoding=utf 8?> <TabHost android:layout_height=fill_parent xml 拓展训练 1- 界面布局 1. 界面布局的重要性做应用程序, 界面是最基本的 Andorid 的界面, 需要写在 res/layout 的 xml 里面, 一般情况下一个 xml 对应一个界面 Android 界面布局有点像写 html( 连注释代码的方式都一样 ), 要先给 Android 定框架, 然后再在框架里面放控件,Android 提供了几种框架,AbsoluteLayout,LinearLayout,

More information

主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new

主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new ListView 自訂排版 主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new int[]{r.drawable.dog1, R.drawable.dog2,

More information

Android 编程基础 Android 开发教程 & 笔记 1

Android 编程基础 Android 开发教程 & 笔记 1 Android 开发教程 & 笔记 1 多式样 ProgressBar 撰写 : 地狱怒兽 联系 :zyf19870302@126.com 普通圆形 ProgressBar 该类型进度条也就是一个表示运转的过程, 例如发送短信, 连接网络等等, 表示一个过程正 在执行中 一般只要在 XML 布局中定义就可以了

More information

Microsoft Word - 第3章.doc

Microsoft Word - 第3章.doc 第 章.1 Android UI 基本概念 用户界面 (User Interface,UI) 是用户与设备之间进行信息交流的直接媒介, 是决定用户体验最重要的部分 相比于早期的计算机的主要交互界面 批处理界面和命令行界面, 现在更为流行的是更简单直接的用户图形界面 (Graphical User Interface, GUI) GUI 简单易用, 受众面广, 直接推动了个人计算机的发展 目前, 主流大众的操作系统都采用了

More information

人民邮电

人民邮电 第 2 章 布 局 布 局 是 所 有 带 界 面 的 Android 程 序 的 开 端 布 局 应 用 得 好 坏 直 接 决 定 了 程 序 的 用 户 体 验 虽 然 布 局 看 似 没 有 组 件 复 杂, 但 也 涉 及 到 了 很 多 技 巧 在 各 大 公 司 的 面 试 题 中 也 会 经 常 遇 到 关 于 布 局 的 一 些 问 题 通 过 这 些 问 题 可 以 考 查 应

More information

Dynamic Layout in Android

Dynamic Layout in Android Dynamic Layout in Android 建國科技大學資管系 饒瑞佶 2013/5 V1 Layout 多半都透過 res/layout/xml 格式設定來達成 Android 是 OOP, 所以可以動態產生 Layout 重點是 Layout 的階層關係 (Hierarchy) 需要處理對應事件 最後一樣用 setcontentview 加入 Layout 一 加入現有 Layout 中

More information

预览图 : (2) 在 SelectCity.java 中增加控件, 用于绑定 select_city 文件的 ListView, TextView,EditTest 等控件 代码和注释如下 :

预览图 : (2) 在 SelectCity.java 中增加控件, 用于绑定 select_city 文件的 ListView, TextView,EditTest 等控件 代码和注释如下 : EditText 实现城市搜索 1801210778 邹宇航 摘要 : 使用 EditText 实现搜索城市的功能, 以此为依据更新 ListView 1. 效果图 : 2. 主要步骤 (1) 在 select-city.xml 布局文件中中添加 EditText 控件用作搜索框, 然后添加 ListView 控件用来显示城市名字内容 代码如下 : 预览图 : (2) 在 SelectCity.java

More information

Microsoft PowerPoint - 05.Android 介面元件-RelativeLayout、Button、TextVeiw、EditText

Microsoft PowerPoint - 05.Android 介面元件-RelativeLayout、Button、TextVeiw、EditText 計劃名稱 : 104 年度教育部資通訊軟體創新人才推升推廣計畫跨校資源中心 : 雲端運算 ( 國立中山大學 ) 課程名稱 : 網路及平台服務 Part1- 課程教材 教材名稱 :Android 介面元件 -RelativeLayout Button TextVeiw EditText 國立高雄大學資訊工程學系張保榮教授 大綱 RelativeLayout 版面配置 Button 版面配置 TextView

More information

01_Service

01_Service 移动平台应用软件开发 Service 主讲 : 张齐勋 zhangqx@ss.pku.edu.cn 移动平台应用软件开发 课程建设小组 北京大学 二零一七年 什么是 Service 与 Activity 一样, 同属 Android 基本组件 后台运行, 不与用户交互, 没有可视化界面 最常见的 Service 如 : 在后台播放歌曲 后台执行文件的下载 同样需在 AndroidManifest.xml

More information

RecyclerView and CardVew

RecyclerView and CardVew RecyclerView and CardView 建國科技大學資管系饒瑞佶 2017/10 V1 CardView CardView A CardView is a ViewGroup. Like any other ViewGroup, it can be added to youractivity or Fragment using a layout XML file. To create an

More information

Android Fragment

Android Fragment Android Fragment 建國科技大學資管系饒瑞佶 2017/10 V1 Android 3.0 後才支援 Fragment 解決部分 App 適應螢幕大小的問題 它類似於 Activity, 可以像 Activity 可以擁有自己的版面設計, 也和 Activity 一樣有自己的生命週期 ( 具備 oncreate() oncreateview() 與 onpause() 方法 ) LifeCycle

More information

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double

More information

The Embedded computing platform

The Embedded computing platform Android User Interfaces Hsiao-Lung Chan, Ph.D. Dept Electrical Engineering Chang Gung University, Taiwan chanhl@maili.cgu.edu.tw Basic control components Text components TextView EditText Button compoents

More information

Microsoft Word - 扉页.doc

Microsoft Word - 扉页.doc 第 3 章 Andro 常用基本控件 我们在进行界面布局时, 添加的按钮 文本框 编辑框和图片等, 都是 Andro 的基本控件 这些控件实现了程序的一些基本功能 本章将针对这类控件进行详细的介绍, 使读者掌握基本控件的使用, 开发出简单的 Andro 程序 3.1 文本控件概述 Andro 系统提供给用户已经封装好的界面控件称为系统控件 系统控件更有利于帮助用户进行快速开发, 同时能够使 Andro

More information

Microsoft Word 杨超-spinner实现省市县的三级联动.docx

Microsoft Word 杨超-spinner实现省市县的三级联动.docx Spinner 实现省市县的三级联动 1801210908- 杨超 下拉框 Spinner 控件 : 常用属性 属性 说明 android:prompt 下拉提示信息 android:spinnermode 下拉显示方法 android:entries 配置下拉框数据源 android:dropdownwidth 下拉框显示模式下的显示项宽度 常用方法 方法 说明 getdropdownwidth()

More information

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP:  ******************* * 关于 Java 测试试题 ****** ******************* * 关于 Java 测试试题 ******************* 問 1 运行下面的程序, 选出一个正确的运行结果 public class Sample { public static void main(string[] args) { int[] test = { 1, 2, 3, 4, 5 ; for(int i = 1 ; i System.out.print(test[i]);

More information

任务实施 (1) 创建项目 图 3-1 欢迎界面 首先创建一个工程, 将其命名为 BoXueGu, 指定包名为 com.boxuegu (2) 导入界面图片将欢迎界面所需要的背景图片 launch_bg.png 导入到 drawable 文件夹中, 项目的 icon 图标 app_icon.png

任务实施 (1) 创建项目 图 3-1 欢迎界面 首先创建一个工程, 将其命名为 BoXueGu, 指定包名为 com.boxuegu (2) 导入界面图片将欢迎界面所需要的背景图片 launch_bg.png 导入到 drawable 文件夹中, 项目的 icon 图标 app_icon.png 第 3 章注册与登录模块 学习目标 掌握欢迎界面的开发, 能够独立制作欢迎界面 ; 掌握注册和登录模块的开发, 能够实现用户登录功能 博学谷项目的注册与登录模块主要用于创建用户账号, 管理用户信息 当用户注册成功后会跳转到登录界面, 用户登录后可以修改密码以及设置密保, 且只有设置过密保的账户才可以找回密码 本章将针对注册与登录模块进行详细讲解 3.1 欢迎界面 任务综述 在实际开发中, 开启应用程序时首先会呈现一个欢迎界面,

More information

單步除錯 (1/10) 打開 Android Studio, 點選 Start a new Android Studio project 建立專案 Application name 輸入 BMI 點下 Next 2 P a g e

單步除錯 (1/10) 打開 Android Studio, 點選 Start a new Android Studio project 建立專案 Application name 輸入 BMI 點下 Next 2 P a g e Android Studio Debugging 本篇教學除了最基本的中斷點教學之外, 還有條件式中斷的教學 條件式中斷是進階的除錯技巧, 在某些特定情況中, 我們有一個函數可能會被呼叫數次, 但是我們只希望在某種條件成立時才進行中斷, 進而觀察變數的狀態 而條件式中斷這項技巧正是符合這項需求 本教學分兩部分 單步除錯 (Page2~11, 共 10) 條件式中斷點 (Page12~17, 共 6)

More information

用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應

用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應 專題進度 老師 : 趙啟時老師 學生 : 陳建廷 2013/10/13 用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應 程式碼 : package com.example.phone; import java.util.arraylist;

More information

Android Service

Android Service Android Service- 播放音樂 建國科技大學資管系 饒瑞佶 2013/7 V1 Android Service Service 是跟 Activity 並行 一個音樂播放程式若沒使用 Service, 即使按 home 鍵畫面離開之後, 音樂還是照播 如果再執行一次程式, 新撥放的音樂會跟先前撥放的一起撥, 最後程式就會出錯 執行中的程式完全看不到! 但是, 寫成 Service 就不同了

More information

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 odps-sdk 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基 开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些

More information

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d

More information

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 月 3 日 1 1 INPUTOUTPUT 1 InputOutput 题目描述 用 cin 输入你的姓名 ( 没有空格 ) 和年龄 ( 整数 ), 并用 cout 输出 输入输出符合以下范例 输入 master 999 输出 I am master, 999 years old. 注意 "," 后面有一个空格,"." 结束,

More information

Android + NFC

Android + NFC Android + NFC 建國科技大學資管系饒瑞佶 2017/3 v1 讀取 Tag UUID Android 2.3.3 (API Level 10) 才有支援完整的 NFC 功能 只要 NFC 相容都讀的到 (NFC 或 Mifare) 建立新專案修改 AndroidManifest.xml 加入 , 如果有 NFC Tag 進入感測範圍, 本 App 也會變成可處理的

More information

单击以编辑母片 Content 标题样式 LinearLayout 排版模式 TableLayout 排版模式 RelativeLayout 排版模式 AbsoluteLayout 排版模式 FrameLayout 排版模式 GridLayout 排版模式 TabWidget 切換卡 Lab 5 2

单击以编辑母片 Content 标题样式 LinearLayout 排版模式 TableLayout 排版模式 RelativeLayout 排版模式 AbsoluteLayout 排版模式 FrameLayout 排版模式 GridLayout 排版模式 TabWidget 切換卡 Lab 5 2 单击以编辑母片标题样式 安卓系统 Android 的排版 授课老师 : 谢兆贤 2016/4/18 1 单击以编辑母片 Content 标题样式 LinearLayout 排版模式 TableLayout 排版模式 RelativeLayout 排版模式 AbsoluteLayout 排版模式 FrameLayout 排版模式 GridLayout 排版模式 TabWidget 切換卡 Lab 5

More information

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例 帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例 这篇文章主要介绍了帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例, 本文还详细介绍了帝国 CMS 数据库类中的一些常用方法, 需要的朋友可以参考下 例 1: 连接 MYSQL 数据库例子 (a.php)

More information

1. 2. Flex Adobe 3.

1. 2. Flex Adobe 3. 1. 2. Flex Adobe 3. Flex Adobe Flex Flex Web Flex Flex Flex Adobe Flash Player 9 /rich Internet applications/ria Flex 1. 2. 3. 4. 5. 6. SWF Flash Player Flex 1. Flex framework Adobe Flex 2 framework RIA

More information

建模与图形思考

建模与图形思考 C03_c 基 於 軟 硬 整 合 觀 點 JNI: 从 C 调 用 Java 函 数 ( c) By 高 煥 堂 3 How-to: 基 於 軟 硬 整 合 觀 點 从 C 调 用 Java 函 数 如 果 控 制 点 摆 在 本 地 C 层, 就 会 常 常 1. 从 本 地 C 函 数 去 调 用 Java 函 数 ; 2. 从 本 地 C 函 数 去 存 取 Java 层 对 象 的 属 性

More information

untitled

untitled JavaEE+Android - 6 1.5-2 JavaEE web MIS OA ERP BOSS Android Android Google Map office HTML CSS,java Android + SQL Sever JavaWeb JavaScript/AJAX jquery Java Oracle SSH SSH EJB+JBOSS Android + 1. 2. IDE

More information

可 Web 编程的NativeUI 设计与实现

可 Web 编程的NativeUI  设计与实现 可 Web 编程的 NativeUI 设计与实现 张袁炜 zhangyuanwei@baidu.com 欢迎转岗简历请发 About Me @ 张袁炜 直达号 网址导航 百度 音乐 前端 Node.js Android Arduino RaspberryPI https://github.com/zhangyuanwei Outline 一个 Hybrid App 的进化史 Native UI 实现原理

More information

小应用 Magic8

小应用 Magic8 胡家威 计研135班 http://hujiaweibujidao.github.io/ 小应用 Magic8 Android 系统简介 Android 应用结构 Android 四大组件 Activity 生命周期 Android 资源管理 UI 组件和容器组件 内容概要 ( 上 ) Android 系统简介 Android 市场份额 Android 是如何诞生的? Android 之父 :Andy

More information

Chapter 9: Objects and Classes

Chapter 9: Objects and Classes Java application Java main applet Web applet Runnable Thread CPU Thread 1 Thread 2 Thread 3 CUP Thread 1 Thread 2 Thread 3 ,,. (new) Thread (runnable) start( ) CPU (running) run ( ) blocked CPU sleep(

More information

// HDevelopTemplateWPF projects located under %HALCONEXAMPLES%\c# using System; using HalconDotNet; public partial class HDevelopExport public HTuple

// HDevelopTemplateWPF projects located under %HALCONEXAMPLES%\c# using System; using HalconDotNet; public partial class HDevelopExport public HTuple halcon 与 C# 混合编程之 Halcon 代码调用 写在前面 完成 halcon 与 C# 混合编程的环境配置后, 进行界面布局设计构思每一个按钮所需要实现 的功能, 将 Halcon 导出的代码复制至相应的 C# 模块下即可 halcon 源程序 : dev_open_window(0, 0, 512, 512, 'black', WindowHandle) read_image (Image,

More information

Microsoft Word - 第4章 3D相册.doc

Microsoft Word - 第4章 3D相册.doc 第 4 章 3D 相册 学习目标 u 掌握相册界面的开发, 实现相册的立体与倒影效果 在现实生活中, 我们浏览照片时, 不同的相册软件有不同的浏览效果 本章主要实现了一个 3D 效果的相册, 该相册中的图片可以循环滑动展示 4.1 3D 相册 任务综述 相册界面主要是展示一组图片的立体效果, 并显示每个图片的倒影, 左右滑动可以切换不同的图片到 界面的中间位置, 同时在图片下方显示当前图片的标题,

More information

Microsoft Word - weather12 刷新按钮动画+搜索框+bug处理.docx

Microsoft Word - weather12 刷新按钮动画+搜索框+bug处理.docx 一 刷新按钮的动画效果 : 在刷新按钮的位置做两个按钮的布局, 一个是原来的静态图片, 一个是旋转的动画, 然 后控制这两个效果的显示和隐藏 ( 一 ) 刷新按钮的 style: 1. 在 app/src/main/res/values/ styles.xml 文件里添加一个 style: 2. 在 drawable 文件夹下新建一个 title_update_anim.xml, 添加如下内容 注

More information

untitled

untitled 1 行 行 行 行.NET 行 行 類 來 行 行 Thread 類 行 System.Threading 來 類 Thread 類 (1) public Thread(ThreadStart start ); Name 行 IsAlive 行 行狀 Start 行 行 Suspend 行 Resume 行 行 Thread 類 (2) Sleep 行 CurrentThread 行 ThreadStart

More information

Microsoft PowerPoint - 07.Android 介面元件-TableLayout、Toast、AlertDialog

Microsoft PowerPoint - 07.Android 介面元件-TableLayout、Toast、AlertDialog 計劃名稱 : 104 年度教育部資通訊軟體創新人才推升推廣計畫跨校資源中心 : 雲端運算 ( 國立中山大學 ) 課程名稱 : 網路及平台服務 Part1- 課程教材 教材名稱 :Android 介面元件 -TableLayout Toast AlertDialog 國立高雄大學資訊工程學系張保榮教授 大綱 TableLayout 版面配置 Toast 版面配置 AlertDialog 版面配置 TableLayout

More information

一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页

一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页 第 1 页共 32 页 crm Mobile V1.0 for IOS 用户手册 一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页 二 crm Mobile 界面介绍 : 第 3 页共 32 页 三 新建 (New) 功能使用说明 1 选择产品 第 4 页共 32 页 2 填写问题的简要描述和详细描述 第 5 页共

More information

新・解きながら学ぶJava

新・解きながら学ぶJava 481! 41, 74!= 40, 270 " 4 % 23, 25 %% 121 %c 425 %d 121 %o 121 %x 121 & 199 && 48 ' 81, 425 ( ) 14, 17 ( ) 128 ( ) 183 * 23 */ 3, 390 ++ 79 ++ 80 += 93 + 22 + 23 + 279 + 14 + 124 + 7, 148, 16 -- 79 --

More information

图 6-1 主界面 MainActivity 界面对应的布局文件 (activity_main.xml) 如下所示 : <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="

图 6-1 主界面 MainActivity 界面对应的布局文件 (activity_main.xml) 如下所示 : <?xml version=1.0 encoding=utf-8?> <RelativeLayout xmlns:android= 第 6 章广播接收者 应用案例 案例 6-1 CallRecord( 通话记录 ) 一 案例描述 1 考核知识点 030006001: 广播接收者简介 030006002: 广播接收者的创建 2 练习目标 广播的静态注册和使用 使用广播处理处理事件 3 需求分析手机最重要的功能就是通话功能, 同样储存通话记录也是必不可少的 该案例使用广 播接收者自己实现通话记录的功能 包括呼出电话 已接来电 未接来电以及通话产生的

More information

Microsoft Word - Android 7.x.doc

Microsoft Word - Android 7.x.doc 第 4 章 Android GUI 开发 Android 系统提供了丰富的可视化界面组件, 包括菜单 按钮 对话框等 Android 系统采用 Java 程序设计中的 UI 设计思想, 其中包括事件处理机制及布局管理方式 Android 系统中的所有 UI 类都是建立在 View 和 ViewGroup 两个类的基础之上的, 所有 View 的子类称为 Widget, 所有 ViewGroup 的子类称为

More information

Android 开发教程

Android 开发教程 封面 1 GUI 可视化设计器 DroidDraw DroidDraw 是一个基于 Java Swing 的 Android 界面设计器, 可以通过它来生成复杂的 Android Layout XML 文 件,Android 的 Layout 和 Swing Layout 中有很好的对应, 设计器的代码编写起来比较容易 2 AnDroidDraw AnDroidDraw 是一个与 DroidDraw

More information

付宝容器 jsapi 档 册 PDF 版本 本版本为实验版本, 为线下独 查看使, 受制于 成 PDF 程序的限制, 样式问题还没有很好的解决, 例如分 切图 代码 亮 推荐使 在线版本, 便实时查看 jsapi 运 效果 如需搜索, 使 阅读 PDF 软件 带功能即可 更多细节样式调整和 录索引探

付宝容器 jsapi 档 册 PDF 版本 本版本为实验版本, 为线下独 查看使, 受制于 成 PDF 程序的限制, 样式问题还没有很好的解决, 例如分 切图 代码 亮 推荐使 在线版本, 便实时查看 jsapi 运 效果 如需搜索, 使 阅读 PDF 软件 带功能即可 更多细节样式调整和 录索引探 付宝容器 jsapi 档 册 PDF 版本 本版本为实验版本, 为线下独 查看使, 受制于 成 PDF 程序的限制, 样式问题还没有很好的解决, 例如分 切图 代码 亮 推荐使 在线版本, 便实时查看 jsapi 运 效果 如需搜索, 使 阅读 PDF 软件 带功能即可 更多细节样式调整和 录索引探索建设中 成时间 : 2017-07-20 12:13:21 Since 8.6 定义键盘 定义键盘使

More information

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 -> 目录 1 大概思路... 1 2 创建 WebAPI... 1 3 创建 CrossMainController 并编写... 1 4 Nuget 安装 microsoft.aspnet.webapi.cors... 4 5 跨域设置路由... 4 6 编写 Jquery EasyUI 界面... 5 7 运行效果... 7 8 总结... 7 1 1 大概思路 创建 WebAPI 创建 CrossMainController

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 按钮对象 (button) 当 JavaScript 读到 标记中的 type 属性值为 button 时, 自动建立一个按钮对象, 并将该对象放到表单对象的 elements 数组当中 按钮对象包括 : 普通按钮 (button) 提交按钮 (submit) 重置按钮 (reset) 1. 使用按钮对象的格式 document.forms[ 索引值 ].elements[ 索引值

More information

Android线程和进程

Android线程和进程 Android 进程和线程 版权声明 华清远见教育集团版权所有 ; 未经华清远见明确许可, 不得为任何目的以任何形式复制或传播此文档的任何部分 ; 本文档包含的信息如有更改, 恕不另行通知 ; 华清远见教育集团保留所有权利 Android 进程和线程 在安装 Android 应用程序的时候,Android 会为每个程序分配一个 Linux 用户 ID, 并设置相应的权限, 这样其它应用程序就不能访问此应用程序所拥有的数据和资源了

More information

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入 100 年 特 種 考 試 地 方 政 府 公 務 人 員 考 試 試 題 等 別 : 三 等 考 試 類 科 : 資 訊 處 理 科 目 : 系 統 分 析 與 設 計 一 請 參 考 下 列 旅 館 管 理 系 統 的 使 用 案 例 圖 (Use Case Diagram) 撰 寫 預 約 房 間 的 使 用 案 例 規 格 書 (Use Case Specification), 繪 出 入

More information

第四章 102 图 4唱16 基于图像渲染的理论基础 三张拍摄图像以及它们投影到球面上生成的球面图像 拼图的圆心是相同的 而拼图是由球面图像上的弧线图像组成的 因此我 们称之为同心球拼图 如图 4唱18 所示 这些拼图中半径最大的是圆 Ck 最小的是圆 C0 设圆 Ck 的半径为 r 虚拟相机水平视域为 θ 有 r R sin θ 2 4畅11 由此可见 构造同心球拼图的过程实际上就是对投影图像中的弧线图像

More information

Microsoft Word - 第3章.doc

Microsoft Word - 第3章.doc Java C++ Pascal C# C# if if if for while do while foreach while do while C# 3.1.1 ; 3-1 ischeck Test() While ischeck while static bool ischeck = true; public static void Test() while (ischeck) ; ischeck

More information

Microsoft PowerPoint - ch6 [相容模式]

Microsoft PowerPoint - ch6 [相容模式] UiBinder wzyang@asia.edu.tw UiBinder Java GWT UiBinder XML UI i18n (widget) 1 2 UiBinder HelloWidget.ui.xml: UI HelloWidgetBinder HelloWidget.java XML UI Owner class ( Composite ) UI XML UiBinder: Owner

More information

教案模板4-2

教案模板4-2 移动终端开发技术 电子教案 第三单元 ListView 的功能和用法 章节名称 : 第二章 软件要美观 UI 开发的点点滴滴 所属专业 ( 教研室 ): 计算机软件技术 制定人 : 陈媛媛 合作人 : 制定时间 : 2018 年 2 月 日照职业技术学院 单元标题 ListView 的功能和用法 单元教学学时 在整体设计中的位置 4 课时 第 7 次 授课班级上课地点一体化教室 上课时间周月日第节

More information

Microsoft Word - 01.DOC

Microsoft Word - 01.DOC 第 1 章 JavaScript 简 介 JavaScript 是 NetScape 公 司 为 Navigator 浏 览 器 开 发 的, 是 写 在 HTML 文 件 中 的 一 种 脚 本 语 言, 能 实 现 网 页 内 容 的 交 互 显 示 当 用 户 在 客 户 端 显 示 该 网 页 时, 浏 览 器 就 会 执 行 JavaScript 程 序, 用 户 通 过 交 互 式 的

More information

第一章 Android 简介与开发环境搭建

第一章 Android 简介与开发环境搭建 安卓开发环境与常用布局 第一章 Android 简介与开发环境搭建 本章目标 3G 的概念 Android 的改变 Android 开发环境的搭建编写第一个 Android 程序 Android 程序的目录结构 手机发展史 1. 3G 的概念 3G 全称为 :3rd Generation, 中文含义即为第三代数字通信, 是指将无线通信与国际互联网等多媒体通信结合的新一代移动通信系统 2. 符合 3G

More information

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d =

More information

Microsoft Word - AEL CH05.doc

Microsoft Word - AEL CH05.doc 5-2 AutoCompleteTextView AutoCompleteTextView 非常類似 EditText, 屬於文字輸入方塊 ; 不過 AutoCompleteTextView 會在使用者輸入幾個字時就會顯示提示文字, 方便使用者選取而無需輸入所有文字, 是一種體貼使用者輸入的設計 AutoCompleteTextView 的提示列表與 Spinner 的選項列表建立方式相同, 需要建立字串陣列來儲存欲提示的文字

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 The BitCoin Scripting Language 交易实例 交易结构 "result": { "txid": "921a dd24", "hash": "921a dd24", "version": 1, "size": 226, "locktime": 0, "vin": [ ], "vout": [ ], "blockhash": "0000000000000000002c510d

More information

Chapter 4

Chapter 4 Chapter 4 手機控制項應用 元件佈局 線性佈局共有兩個方向 : 垂直 (vertical) 水帄 (horizontal) 決定垂直或是水帄的屬性為 Orientation android:orientation="vertical" 線性佈局就是將在 < LinearLayout > 內的元件以線性的方式來呈現

More information

Microsoft Word - CX1000-HMI_程序开发_PLC通讯

Microsoft Word - CX1000-HMI_程序开发_PLC通讯 用 VB.Net 开发 CX1000 的 HMI 第二部分和 TwinCAT PLC 通讯 一 TwinCAT 动态库 TwinCAT.Ads.dll The TwinCAT.Ads.dll 是一个.NET 类库, 它提供和 ADS 设备通讯的类 如果 TwinCAT PLC 运行在 IPC 上, 则需要添加的类库是路径 \TwinCAT\ADS Api\.NET\v1.1.4322 下的 TwinCAT.Ads.dll

More information

Guava学习之Resources

Guava学习之Resources Resources 提供提供操作 classpath 路径下所有资源的方法 除非另有说明, 否则类中所有方法的参数都不能为 null 虽然有些方法的参数是 URL 类型的, 但是这些方法实现通常不是以 HTTP 完成的 ; 同时这些资源也非 classpath 路径下的 下面两个函数都是根据资源的名称得到其绝对路径, 从函数里面可以看出,Resources 类中的 getresource 函数都是基于

More information

Microsoft Word - 第3章.doc

Microsoft Word - 第3章.doc 第 3 章 Android 控件进阶 要设计出让用户喜欢的 Android 应用程序界面, 除了需要用到在第 2 章讲的最基本的 TextView EditText 和 Button 控件外, 还要用到其他控件, 如 ImageButton 控件 ImageView 控件 RadioButton 控件 CheckBox 控件和 ListView 控件等 本章主要讲解功能强大 应用广泛的一些控件 3.1

More information

Android Android Android SDK iv

Android Android Android SDK iv Android Market Google Android SDK Apple Google Microsoft b2c b 2010 Internet Android how why iii Android 240... Android Android SDK iv Android Market Google Android SDK Visual C++ Java N-tier J2EE Unix/Linux

More information

Microsoft PowerPoint - 08_Android_Spring11_Control2.pptx

Microsoft PowerPoint - 08_Android_Spring11_Control2.pptx 作者 : 李昭賢作者 : 洪振偉編撰整理者 : 陳彥霖 學習目標 1. 透過 XML 產生控制項 2. 透過 Java 產生控制項 3. 新增事件 (Event) 處理 AnalogClock / DigitalClock 負責顯示時間 AnalogClock: 以傳統鐘錶指針方式顯示時與分 DigitalClock: 以數位數字方式顯示時 分與秒 類比小時鐘 (AnalogClock 類別 ) 數位小時鐘

More information

软件工程文档编制

软件工程文档编制 实训抽象类 一 实训目标 掌握抽象类的定义 使用 掌握运行时多态 二 知识点 抽象类的语法格式如下 : public abstract class ClassName abstract void 方法名称 ( 参数 ); // 非抽象方法的实现代码 在使用抽象类时需要注意如下几点 : 1 抽象类不能被实例化, 实例化的工作应该交由它的子类来完成 2 抽象方法必须由子类来进行重写 3 只要包含一个抽象方法的抽象类,

More information

拦截器(Interceptor)的学习

拦截器(Interceptor)的学习 二 拦截器 (Interceptor) 的学习 拦截器可以监听程序的一个或所有方法 拦截器对方法调用流提供了细粒度控制 可以在无状态会话 bean 有状态会话 bean 和消息驱动 bean 上使用它们 拦截器可以是同一 bean 类中的方法或是一个外部类 下面介绍如何在 Session Bean 类中使用外部拦截器类 @Interceptors 注释指定一个或多个在外部类中定义的拦截器 下面拦截器

More information

Microsoft Word - Broker.doc

Microsoft Word - Broker.doc Broker 模式 采用 broker 模式对分布式计算进行简单模拟 系统在一个进程内模拟分布式环境, 因此不涉及网络编程和进程间通信,Broker 通过本地函数调用的方式实现 request 和 response 的转发 采用 broker 模式对分布式计算进行简单的模拟, 要求如下 : 设计四个 server, 一个 server 接收两个整数, 求和并返回结果, 一个 server 接收两个整数,

More information

untitled

untitled 1 LinkButton LinkButton 連 Button Text Visible Click HyperLink HyperLink 來 立 連 Text ImageUrl ( ) NavigateUrl 連 Target 連 _blank _parent frameset _search _self 連 _top 例 sample2-a1 易 連 private void Page_Load(object

More information

1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10

1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10 Java V1.0.1 2007 4 10 1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10 6.2.10 6.3..10 6.4 11 7.12 7.1

More information

1 下列类头定义中, 正确的是 面向对象程序设计网络课程 A class x { } B public x extends y { } C public class x extends y {.} D class x extends y implements y1 { } 2 现有两个类 A B,

1 下列类头定义中, 正确的是 面向对象程序设计网络课程 A class x { } B public x extends y { } C public class x extends y {.} D class x extends y implements y1 { } 2 现有两个类 A B, 1 下列类头定义中, 正确的是 A class x B public x extends y C public class x extends y. D class x extends y implements y1 2 现有两个类 A B, 以下描述中表示 B 继承自 A 的是 (D ) A) class A extends B B) class B implements A C) class A

More information

手说TTS开发指南

手说TTS开发指南 手说 TTS 开发指南 v1.3 2011 年 6 月 版权所有 : 手说工作室 shoushuo.com 版本时间作者说明 1.0 2010-11-15 张波 1.1 2010-12-27 在 ondestroy 方法 unbindservice 1.2 2010-12-30 1.3 2011-6-12 去掉 TTS 初始化 ; ttsservice.initialize() 方法调用添加接口方法

More information

幻灯片 1

幻灯片 1 Delivering accurate maps to Chinese Android users 为中国安卓用户提供准确的地图服务 Work at Mapbox includes: Android apps, demos, starter kits, documentation, support, syncing Android team with other departments, etc.

More information

LEFT, RIGHT // 左 // 右 (2) 当图片移动后, 按钮的坐标发生改变, 此操作通过 setloca tion() 方法实现 setlocation() 方法是从 Component 类继承的, 其定义如下 : public void setlocation(int x, int y

LEFT, RIGHT // 左 // 右 (2) 当图片移动后, 按钮的坐标发生改变, 此操作通过 setloca tion() 方法实现 setlocation() 方法是从 Component 类继承的, 其定义如下 : public void setlocation(int x, int y 拼图游戏 任务说明 本实例实现了拼图游戏的开发 运行程序, 单击 开始 按钮将打乱图片的位置, 效果如图 1 所示, 然后通过鼠标单击图片进行移动, 直到将所有图片都移动到正确位置, 游戏过关, 过关后的效果如图 2 所示 图 1 打乱图片位置的效果图 2 图片移动到正确位置的效果 关键技术 本程序主要通过 Swing 与枚举类实现, 程序将一幅完整的图片平均分成 9 部分, 每一部分为一个正方形,

More information

ExcelUtility 类库使用说明 ( 续 ) 开发 / 设计 : 左文俊 第一个新增功能, 列宽自适应, 当超过 30 个字符则将单元格内容设为换行 任意一个无模板的导出方法均支持该功能, 示例代码如下 : /// <summary> /// 测试方法

ExcelUtility 类库使用说明 ( 续 ) 开发 / 设计 : 左文俊 第一个新增功能, 列宽自适应, 当超过 30 个字符则将单元格内容设为换行 任意一个无模板的导出方法均支持该功能, 示例代码如下 : /// <summary> /// 测试方法 ExcelUtility 类库使用说明 ( 续 ) 开发 / 设计 : 左文俊 第一个新增功能, 列宽自适应, 当超过 0 个字符则将单元格内容设为换行 任意一个无模板的导出方法均支持该功能, 示例代码如下 : 0 /// 测试方法 : 测试将 DataTable 导出到 EXCEL, 无模板 public void TestExportToExcelByDataTable() string excelpath

More information

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复 获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复 获取将导致上次获取的 access_token 失效 接入方可以使用 AppID 和 AppSecret

More information

无类继承.key

无类继承.key 无类继承 JavaScript 面向对象的根基 周爱 民 / aimingoo aiming@gmail.com https://aimingoo.github.io https://github.com/aimingoo rand = new Person("Rand McKinnon",... https://docs.oracle.com/cd/e19957-01/816-6408-10/object.htm#1193255

More information

内文-2.indd

内文-2.indd 客户端服务端音乐资源信息 : 1. 项目需求从本项目开始, 我们一起开发一个简单的在线音乐播放器, 它具有以下功能 (1) 程序启动时显示一个启动画面, 如图 1-1 所示 (2) 在程序主页面显示服务器上的歌曲列表, 包括歌手名与歌曲名, 单击列表条目可实现在线音乐播放, 单击 播放 暂停 上一曲 下一曲 按钮可实现对应的功能, 进度条可以显示歌曲播放进度, 如图 1-2 所示 图 1-1 程序启动画面

More information

C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1 1 TEMPLATE 1 Template 描述 使用模板函数求最大值 使用如下 main 函数对程序进行测试 int main() { double a, b; cin >> a >> b; cout c >> d; cout

More information

PowerPoint 簡報

PowerPoint 簡報 UI 設計 Android 專案目錄架構 Android 專案建立後會自動產生 3 個主要目錄 src:java 程式檔案 res: 資源 ( 文字 圖形 聲音檔案等 ) 與 UI 設定有關的 layout 檔 此目錄內檔案名稱只能為小寫字母 數字 _. gen:r.java 根據 res 目錄內容自動產生 不要去修改 R.java Android 中所有的資源檔案 ( 圖片 XML 等 ) 命名都必須使用英文小寫,

More information

使用MapReduce读取XML文件

使用MapReduce读取XML文件 使用 MapReduce 读取 XML 文件 XML( 可扩展标记语言, 英语 :extensible Markup Language, 简称 : XML) 是一种标记语言, 也是行业标准数据交换交换格式, 它很适合在系统之间进行数据存储和交换 ( 话说 Hadoop H ive 等的配置文件就是 XML 格式的 ) 本文将介绍如何使用 MapReduce 来读取 XML 文件 但是 Had oop

More information

<C8EBC3C5C6AAA3A8B5DA31D5C2A3A92E696E6464>

<C8EBC3C5C6AAA3A8B5DA31D5C2A3A92E696E6464> 第 1 章 进入 Photoshop 的全新世界 本章导读 Photoshop 1 1.1 Photoshop CS6 Photoshop Photoshop 1.1.1 Photoshop POP 1-1 图 1-1 平面广告效果 1.1.2 Photoshop 1-2 Photoshop CS6 Photoshop CS6 Photoshop CS6 Extended 3D 3 Photoshop

More information

Android Robert C.C. Huang Oscar F.Y. Liu Peter C.L. Hsieh 2011/03/21

Android Robert C.C. Huang Oscar F.Y. Liu Peter C.L. Hsieh 2011/03/21 Android Robert C.C. Huang Oscar F.Y. Liu Peter C.L. Hsieh 2011/03/21 Outlines for Today Future Planning Review System Architecture Dev. Tools & Making the First App Project Structure & File Details Application

More information

Microsoft PowerPoint - 04 界面编程.ppt [兼容模式]

Microsoft PowerPoint - 04 界面编程.ppt [兼容模式] 手机应用平台软件开发 4 界面编程 刘宁 Email:liuning2@mail.sysu.edu.cn UI 简介 UI(User Interface) 用户界面系统和用户之间进行交互和信息交换的媒介, 主要作用是实现信息内部形式与人类可接受形式之间的转换 人机交互实践中, 一个好的界面设计不仅让软件变得更加有个性和创意, 同时还能让软件的操作变得舒适 简单 自由, 充分体现软件的定位和特点 一个友好美观的界面会给人带来舒适的视觉享受,

More information

_banneradview.settest(true); _banneradview.setuserkeywords("swimming"); _banneradview.setusercategories("1,3,4"); _banneradview.setusergender(jdbanner

_banneradview.settest(true); _banneradview.setuserkeywords(swimming); _banneradview.setusercategories(1,3,4); _banneradview.setusergender(jdbanner 京东 APP 联盟 SDK Android 版接口说明文档 1.0 1. 嵌入 SDK 1.1 添加 SDK Android Studio 环境 : 菜单 New->New Module->Import.jar or.aar package, 然后选中 App 联盟 SDK 所带的 jar 文件 Eclipse+ADT 环境 : 将 App 联盟 SDK 所带的 jar 文件拷贝到 libs/ 目录下

More information

5-1 nav css 5-2

5-1 nav css 5-2 5 HTML CSS HTML CSS Ê Ê Ê Ê 5-1 nav css 5-2 5-1 5 5-1-1 5-01 css images 01 index.html 02 5-3 style.css css 03 CH5/5-01/images 04 images index.html style.css 05

More information

EJB-Programming-4-cn.doc

EJB-Programming-4-cn.doc EJB (4) : (Entity Bean Value Object ) JBuilder EJB 2.x CMP EJB Relationships JBuilder EJB Test Client EJB EJB Seminar CMP Entity Beans Session Bean J2EE Session Façade Design Pattern Session Bean Session

More information

第 5 章 Android 控件进阶操作实战 ArrayAdapter 适配器 ListView 的数据渲染都需要借助适配器来完成, 首先看一下结合最简单的 ArrayAdapter 来实现 ListView 主布局文件 (activity_main.xml) 代码如下 : <?

第 5 章 Android 控件进阶操作实战 ArrayAdapter 适配器 ListView 的数据渲染都需要借助适配器来完成, 首先看一下结合最简单的 ArrayAdapter 来实现 ListView 主布局文件 (activity_main.xml) 代码如下 : <? 108 Android 开发入门百战经典 第 5 章 Android 控件进阶操作实战 5.1 控之经典 ListView ListView 是最经典的控件之一, 虽然现在其江山地位不稳, 将要被 RecylerView 取 代, 但设计理念是很经典的, 而且很多程序员还是习惯了 ListView, 因此我们还需要对 ListView 进行深入学习 ListView 内容非常多, 读者要有足够的耐心进行学习,

More information

Microsoft Word - 第3章 Activity.doc

Microsoft Word - 第3章 Activity.doc 第 3 章 Activity 学习目标 u 掌握 Activity 的生命周期 u 掌握 Activity 的四种启动模式 u 掌握显式意图和隐式意图的使用 u 学会使用 Intent 传递数据在现实生活中, 经常会使用手机进行打电话 发短信 玩游戏等, 这就需要与手机界面进行交互 在 Android 系统中, 用户与程序的交互是通过 Activity 完成的 同时 Activity 也是 Android

More information

DU Ad Platform_SDK 安卓接入指南 DU Ad Platform_SDK for Android 接入手册 ( 触发式广告 ) DUAd_SDK_Trigger v1.0 百度在线网络技术 ( 北京 ) 有限公司 百度在线网络技术 ( 北京 ) 有限公司 - 1 -

DU Ad Platform_SDK 安卓接入指南 DU Ad Platform_SDK for Android 接入手册 ( 触发式广告 ) DUAd_SDK_Trigger v1.0 百度在线网络技术 ( 北京 ) 有限公司 百度在线网络技术 ( 北京 ) 有限公司 - 1 - DU Ad Platform_SDK for Android 接入手册 ( 触发式广告 ) DUAd_SDK_Trigger v1.0-1 - 目录 1. 获取身份... 1 2. 加载与配置... 2 2.1 加载 SDK 文件... 2 2.2 配置 AndroidManifest.xml... 2 2.3 混淆代码... 3 3. 初始化... 4 4. 功能使用... 4 第 1 页共 1

More information

在Spring中使用Kafka:Producer篇

在Spring中使用Kafka:Producer篇 在某些情况下, 我们可能会在 Spring 中将一些 WEB 上的信息发送到 Kafka 中, 这时候我们就需要在 Spring 中编写 Producer 相关的代码了 ; 不过高兴的是,Spring 本身提供了操作 Kafka 的相关类库, 我们可以直接通过 xml 文件配置然后直接在后端的代码中使用 Kafka, 非常地方便 本文将介绍如果在 Spring 中将消息发送到 Kafka 在这之前,

More information

0511-Android程式之GPS應用_專題週記4

0511-Android程式之GPS應用_專題週記4 逢甲大學通訊工程學系專題研究 Android 程式之 GPS 應用 專題週記 0511 學生姓名 陳彥儒 D0035131 廖元譽 D0077791 指導老師 楊豐瑞老師繳交日期 2014.05.11 1 匯入 GoogleMap 1.1 取得授權步驟 目前進度 取得 Google 授權鑰匙 實作程式尚未成功 1.1.1 建立個人的 keystore 1.1.2 由個人的 keystore 查詢 SHA1

More information

建立Android新專案

建立Android新專案 Android 智 慧 型 手 機 程 式 設 計 Android WebService 建 國 科 技 大 學 資 管 系 饒 瑞 佶 2012/4 V1 2012/8 V2 2013/5 V3 2014/10 v4 提 醒 這 節 的 內 容 針 對 的 是 MS 的 Web Service 或 是 使 用 SOAP(Simple Object Access Protocol) 標 準 建 立

More information

移动平台期末展示

移动平台期末展示 移动平台开发作品展示 周芳张文杰谢殊凡 作品简介 一 作品简介 Ø 应用名称 : 一笔画 Ø 功能 : 随机生成一笔画图案 玩家可以在屏幕上描绘图案, 程序会判定绘制成功或者失败 Ø 设计目的 : 制作一个休闲益智类的小游戏 设计思路 二 设计思路 Ø 1. 自动生成随机的一笔画 奇顶点 : 指数为奇数的顶点 偶顶点 : 指数为偶数的顶点 一笔画图形的必要条件是 : 奇顶点数目是 0 或者 2 Ø

More information

fvalue = (pdata[y][i] + pdata[y][i + 1]) / 2; pdata[y][nhalfw + i] -= fvalue; fvalue = (pdata[y][nhalfw - 1] + pdata[y][nhalfw - 2]) / 2; pdata[y][nwi

fvalue = (pdata[y][i] + pdata[y][i + 1]) / 2; pdata[y][nhalfw + i] -= fvalue; fvalue = (pdata[y][nhalfw - 1] + pdata[y][nhalfw - 2]) / 2; pdata[y][nwi #include #include #include // 二维离散小波变换 ( 单通道浮点图像 ) void DWT(IplImage *pimage, int nlayer) // 执行条件 if (pimage) if (pimage->nchannels == 1 && pimage->depth == IPL_DEPTH_32F

More information

概述

概述 Android Material Design 基础 北京理工大学计算机学院金旭亮 概述 概述 Material Design 是 Google 提出的一种 UI 设计风格, 主要用在 Android App 的开发中, 同时, 也为 AngularJS 提供了相应的组件, 可以用于开发具有 Material Design 风格的网页 设置 Material 主题 Material Design 其实是一种

More information

untitled

untitled 1 Outline 數 料 數 數 列 亂數 練 數 數 數 來 數 數 來 數 料 利 料 來 數 A-Z a-z _ () 不 數 0-9 數 不 數 SCHOOL School school 數 讀 school_name schoolname 易 不 C# my name 7_eleven B&Q new C# (1) public protected private params override

More information

图形学 Project 2 要求 任意两个多边形, 求出其相交的区域 使用说明 例 1 第一步, 与 Project 1 画多边形的方法相同, 画一个多边形 ; 第二步, 单击 INTERSECT WITH, 随后画出第二个多边形 ; 第三步, 单击 FILL 进行填充

图形学 Project 2 要求 任意两个多边形, 求出其相交的区域 使用说明 例 1 第一步, 与 Project 1 画多边形的方法相同, 画一个多边形 ; 第二步, 单击 INTERSECT WITH, 随后画出第二个多边形 ; 第三步, 单击 FILL 进行填充 图形学 Project 2 要求 任意两个多边形, 求出其相交的区域 使用说明 例 1 第一步, 与 Project 1 画多边形的方法相同, 画一个多边形 ; 第二步, 单击 INTERSECT WITH, 随后画出第二个多边形 ; 第三步, 单击 FILL 进行填充 例 2 单击 CLEAR, 重新回到初始状态, 下面让我们看一下自交多边形的情况 当单击数次后, 出现左图的情况, 之后我们单击

More information

Android 基礎教學

Android 基礎教學 Android 基礎教學 吳柏翰 1 Outline Android 歷史起源 Android 優勢與市場未來趨勢 安裝 Android SDK 建立專案 模擬器的執行與操作 使用 Log 及 IDE 除錯工具 實機運作 2 Android 歷史起源 起源 隨著手機與網際網路結合, 上網普及化之後, 使用者對手機的功能有截然不同的需求 透過網際網路, 各種新的服務與應用應運而生, 使用者也希望手機平台能像電腦一樣,

More information

IsPostBack 2

IsPostBack 2 5 IsPostBack 2 TextBox 3 TextBox TextBox 4 TextBox TextBox 1 2 5 TextBox Columns MaxLength ReadOnly Rows Text TextMode TextMode MultiLine TextMode MultiLine True False TextMode MultiLine Password MulitLine

More information

中 文 摘 要 智 慧 型 手 機 由 於 有 強 大 的 功 能, 以 及 優 渥 的 便 利 性, 還 能 與 網 路 保 持 隨 時 的 鏈 結 與 同 步 更 新, 因 此 深 受 廣 大 消 費 者 喜 愛, 當 然, 手 機 遊 戲 也 成 為 現 代 人 不 可 或 缺 的 娛 樂 之

中 文 摘 要 智 慧 型 手 機 由 於 有 強 大 的 功 能, 以 及 優 渥 的 便 利 性, 還 能 與 網 路 保 持 隨 時 的 鏈 結 與 同 步 更 新, 因 此 深 受 廣 大 消 費 者 喜 愛, 當 然, 手 機 遊 戲 也 成 為 現 代 人 不 可 或 缺 的 娛 樂 之 臺 北 市 大 安 高 級 工 業 職 業 學 校 資 訊 科 一 百 零 一 學 年 度 專 題 製 作 報 告 ------ 以 Android 製 作 ------ ----- 連 線 塔 防 遊 戲 ------ Tower defense game using Internet technology 班 級 : 資 訊 三 甲 組 別 : A9 組 組 員 : 葉 冠 麟 (9906129)

More information

题目

题目 开发 Android 应用 目的 : 帮助大家了解 Android 平台开发 作者 : 王威威 技术爱好 : linux,qt, 嵌入式开发 MSN : wangweiweicdma@hotmail.com Email : wang.weiwei1@ztenc.com.cn wangjiecdma@126.com 下载开发资源 1 下载最新的 Android SDK http://code.google.com/android/download.html

More information