黑马程序员技术交流社区

标题: [阳哥笔记]挑战年薪20W之Android笔记系列—Day02(Android基础)! [打印本页]

作者: 阳哥忠粉    时间: 2015-6-23 18:24
标题: [阳哥笔记]挑战年薪20W之Android笔记系列—Day02(Android基础)!




~爱上海,爱黑马~



笔记总链接:http://bbs.itheima.com/thread-206454-1-1.html

Android基础

    布局介绍

    相对布局(RelativeLayout)

    特点:
    相对布局所有组件可以叠加在一起;各个组件的布局是独立的,互不影响;所有组件的默认位置都是在左上角(顶部、左部对齐)。

    属性:
    android:layout_toRightOf               在指定控件的右边
    android:layout_toLeftOf                 在指定控件的左边
    android:layout_above                     在指定控件的上边
    android:layout_below                     在指定控件的下边
    android:layout_alignBaseline          跟指定控件水平对齐
    android:layout_alignLeft                 跟指定控件左对齐
    android:layout_alignRight              跟指定控件右对齐
    android:layout_alignTop                 跟指定控件顶部对齐
    android:layout_alignBottom           跟指定控件底部对齐
    android:layout_alignParentLeft       是否跟父元素左对齐
    android:layout_alignParentTop        是否跟父元素顶部对齐
    android:layout_alignParentRight      是否跟父元素右对齐
    android:layout_alignParentBottom  是否跟父元素底部对齐
    android:layout_centerVertical           在父元素中垂直居中
    android:layout_centerHorizontal      在父元素中水平居中
    android:layout_centerInParent         在父元素中居中   

    示例1:   

    res\layout\activity_main.xml
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context=".MainActivity" >

  6.     <!-- android:layout_alignParentRight="true"表示与父元素右对齐(这里,父元素指的就是RelativeLayout,而RelativeLayout占满了整个屏幕) -->
  7.     <TextView
  8.         android:layout_width="wrap_content"
  9.         android:layout_height="wrap_content"
  10.         android:text="第一个"
  11.         android:layout_alignParentRight="true"/>
  12.    
  13.     <!-- android:layout_alignParentBottom="true"表示与父元素底部对齐(这里,父元素指的就是RelativeLayout,而RelativeLayout占满了整个屏幕) -->
  14.     <TextView
  15.         android:layout_width="wrap_content"
  16.         android:layout_height="wrap_content"
  17.         android:text="第二个"
  18.         android:layout_alignParentBottom="true"/>
  19.    
  20.     <!-- android:layout_centerVertical="true"表示在父元素中垂直居中(这里,父元素指的就是RelativeLayout,而RelativeLayout占满了整个屏幕) -->
  21.     <TextView
  22.         android:layout_width="wrap_content"
  23.         android:layout_height="wrap_content"
  24.         android:text="第三个"
  25.         android:layout_centerVertical="true"
  26.         />
  27.    
  28.     <!-- android:layout_centerHorizontal="true"表示在父元素中水平居中(这里,父元素指的就是RelativeLayout,而RelativeLayout占满了整个屏幕) -->
  29.     <TextView
  30.         android:layout_width="wrap_content"
  31.         android:layout_height="wrap_content"
  32.         android:text="第四个"
  33.         android:layout_centerHorizontal="true"
  34.         />
  35.    
  36.     <!-- android:layout_centerInParent="true"表示在父元素中水平垂直都居中(这里,父元素指的就是RelativeLayout,而RelativeLayout占满了整个屏幕) -->
  37.     <TextView
  38.         android:layout_width="wrap_content"
  39.         android:layout_height="wrap_content"
  40.         android:text="第五个"
  41.         android:layout_centerInParent="true"
  42.         />
  43. </RelativeLayout>
复制代码
    运行结果:



    示例2:

    res\layout\activity_main.xml
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context=".MainActivity" >

  6.     <TextView
  7.         android:id="@+id/tv1"
  8.         android:layout_width="wrap_content"
  9.         android:layout_height="wrap_content"
  10.         android:text="第一一一一个" />
  11.    
  12.     <!-- android:layout_alignRight="true"表示与指定组件右对齐。 -->
  13.     <!-- @+id/就是为组件添加id,@id就是通过id引用组件 -->
  14.     <TextView
  15.         android:layout_width="wrap_content"
  16.         android:layout_height="wrap_content"
  17.         android:text="第二个"
  18.         android:layout_centerVertical="true"
  19.         android:layout_alignRight="@id/tv1"
  20.         />
  21.    
  22.     <!-- 如果同时使用android:layout_alignRight="true",android:layout_alignLeft="true",组件就会被拉伸 -->
  23.     <TextView
  24.         android:layout_width="wrap_content"
  25.         android:layout_height="wrap_content"
  26.         android:text="第三个"
  27.         android:layout_alignParentBottom="true"
  28.         android:layout_alignRight="@id/tv1"
  29.         android:layout_alignLeft="@id/tv1"
  30.         />
  31. </RelativeLayout>
复制代码
   运行结果:



    示例3:

    res\layout\activity_main.xml
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context=".MainActivity" >

  6.     <TextView
  7.         android:id="@+id/tv1"
  8.         android:layout_width="wrap_content"
  9.         android:layout_height="wrap_content"
  10.         android:text="第一个"
  11.         android:layout_centerHorizontal="true"/>
  12.    
  13.     <!-- android:layout_below="@id/tv1"表示在对应组件的下面 -->
  14.     <TextView
  15.         android:id="@+id/tv2"
  16.         android:layout_width="wrap_content"
  17.         android:layout_height="wrap_content"
  18.         android:text="第二个"
  19.         android:layout_below="@id/tv1"
  20.         />
  21.    
  22.     <!-- android:layout_above="@id/tv2"表示在对应组件的上面 -->
  23.     <TextView
  24.         android:layout_width="wrap_content"
  25.         android:layout_height="wrap_content"
  26.         android:text="第三个"
  27.         android:layout_above="@id/tv2"
  28.         />
  29.    
  30.     <!-- android:layout_toRightOf="@id/tv2"表示在对应组件的右边 -->
  31.     <TextView
  32.         android:layout_width="wrap_content"
  33.         android:layout_height="wrap_content"
  34.         android:text="第四个"
  35.         android:layout_toRightOf="@id/tv2"
  36.         />
  37. </RelativeLayout>
复制代码
    运行结果:



    练习:实现如下效果。



    代码:

    res\layout\activity_main.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent" >
  6.    
  7.     <Button
  8.         android:id="@+id/center"
  9.         android:layout_width="wrap_content"
  10.         android:layout_height="wrap_content"
  11.         android:text="中间"
  12.         android:layout_centerInParent="true"/>
  13.    
  14.     <Button
  15.         android:layout_width="wrap_content"
  16.         android:layout_height="wrap_content"
  17.         android:text="上边"
  18.         android:layout_above="@id/center"
  19.         android:layout_alignLeft="@id/center"
  20.         android:layout_alignRight="@id/center"/>
  21.    
  22.     <Button
  23.         android:layout_width="wrap_content"
  24.         android:layout_height="wrap_content"
  25.         android:text="下边"
  26.         android:layout_below="@id/center"
  27.         android:layout_alignLeft="@id/center"
  28.         android:layout_alignRight="@id/center"/>
  29.    
  30.     <Button
  31.         android:layout_width="wrap_content"
  32.         android:layout_height="wrap_content"
  33.         android:text="左边"
  34.         android:layout_toLeftOf="@id/center"
  35.         android:layout_alignTop="@id/center"
  36.         android:layout_alignBottom="@id/center"
  37.         android:layout_alignParentLeft="true"/>
  38.    
  39.     <Button
  40.         android:layout_width="wrap_content"
  41.         android:layout_height="wrap_content"
  42.         android:text="右边"
  43.         android:layout_toRightOf="@id/center"
  44.         android:layout_alignTop="@id/center"
  45.         android:layout_alignBottom="@id/center"
  46.         android:layout_alignParentRight="true"/>
  47.    
  48.         <Button
  49.         android:layout_width="wrap_content"
  50.         android:layout_height="wrap_content"
  51.         android:text="左上"
  52.         android:layout_toLeftOf="@id/center"
  53.         android:layout_above="@id/center"
  54.         android:layout_alignParentLeft="true"/>
  55.         
  56.         <Button
  57.         android:layout_width="wrap_content"
  58.         android:layout_height="wrap_content"
  59.         android:text="左下"
  60.         android:layout_toLeftOf="@id/center"
  61.         android:layout_below="@id/center"
  62.         android:layout_alignParentLeft="true"/>
  63.         
  64.         <Button
  65.         android:layout_width="wrap_content"
  66.         android:layout_height="wrap_content"
  67.         android:text="右上"
  68.         android:layout_toRightOf="@id/center"
  69.         android:layout_above="@id/center"
  70.         android:layout_alignParentRight="true"/>
  71.         
  72.         <Button
  73.         android:layout_width="wrap_content"
  74.         android:layout_height="wrap_content"
  75.         android:text="右下"
  76.         android:layout_toRightOf="@id/center"
  77.         android:layout_below="@id/center"
  78.         android:layout_alignParentRight="true"/>
  79.    
  80. </RelativeLayout>
复制代码
   运行结果:



    帧布局(FrameLayout)

    特点:
    帧布局和相对布局一样,组件可以重叠;所有组件的默认位置是在左上角(顶部、左部对齐)。
   
    示例:

    res\layout\activity_main.xml
  1. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context=".MainActivity" >
  6.    
  7.     <!-- 帧布局中,修改组件的位置使用android:layout_gravity -->
  8.     <TextView
  9.         android:layout_width="wrap_content"
  10.         android:layout_height="wrap_content"
  11.         android:text="第一个"
  12.         android:layout_gravity="right"
  13.         />
  14.    
  15.     <!-- android:layout_gravity="bottom|right" ,表示组件的位置在右下角 -->
  16.     <TextView
  17.         android:layout_width="wrap_content"
  18.         android:layout_height="wrap_content"
  19.         android:text="第二个"
  20.         android:layout_gravity="bottom|right"
  21.         />
  22.    
  23.     <TextView
  24.         android:layout_width="wrap_content"
  25.         android:layout_height="wrap_content"
  26.         android:text="第三个"
  27.         android:layout_gravity="center"
  28.         />
  29.    
  30. </FrameLayout>
复制代码
   运行结果:



    练习:实现如下效果。


    代码:

    res\layout\activity_main.xml
  1. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context=".MainActivity" >
  6.    
  7.     <TextView
  8.         android:layout_width="240dp"
  9.         android:layout_height="240dp"
  10.         android:background="#ff0000"
  11.         android:layout_gravity="center"
  12.         />
  13.    
  14.     <TextView
  15.         android:layout_width="200dp"
  16.         android:layout_height="200dp"
  17.         android:background="#00ff00"
  18.         android:layout_gravity="center"
  19.         />
  20.    
  21.     <TextView
  22.         android:layout_width="160dp"
  23.         android:layout_height="160dp"
  24.         android:background="#0000ff"
  25.         android:layout_gravity="center"
  26.         />
  27.    
  28.     <TextView
  29.         android:layout_width="120dp"
  30.         android:layout_height="120dp"
  31.         android:background="#ffff00"
  32.         android:layout_gravity="center"
  33.         />
  34.    
  35.     <TextView
  36.         android:layout_width="80dp"
  37.         android:layout_height="80dp"
  38.         android:background="#ff00ff"
  39.         android:layout_gravity="center"
  40.         />
  41.    
  42.     <TextView
  43.         android:layout_width="40dp"
  44.         android:layout_height="40dp"
  45.         android:background="#ffffff"
  46.         android:layout_gravity="center"
  47.         />
  48.    
  49. </FrameLayout>
复制代码
   运行结果:


    表格布局(TableLayout)

    示例:

    res\layout\activity_main.xml
  1. <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context=".MainActivity" >
  6.    
  7.     <!-- 表格布局宽高可以不用设置,TableRow的宽度只能是match_parent,高度只能是wrap_content。调正宽度可以通过权重解决。-->
  8.     <TableRow>
  9.         
  10.         <TextView
  11.                 android:text="姓名:"/>
  12.         
  13.         <EditText
  14.             android:layout_weight="1"
  15.             />
  16.         
  17.     </TableRow>

  18.     <TableRow>
  19.         
  20.         <TextView
  21.                 android:text="年龄:"/>
  22.         
  23.         <EditText
  24.             android:layout_weight="1"
  25.             />
  26.         
  27.     </TableRow>
  28.    
  29. </TableLayout>
复制代码
   运行结果:


    绝对布局(AbsoluteLayout)

    绝对布局是直接使用android:layout_x,android:layout_y定位控件的坐标,做不了屏幕适配,所以不常使用。某些没有必要做屏幕适配的开发可以用绝对布局,例如:电视屏幕固定,做机顶盒开发。

    示例:

    res\layout\activity_main.xml
  1. <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context=".MainActivity" >

  6.     <Button
  7.         android:id="@+id/button1"
  8.         android:layout_width="wrap_content"
  9.         android:layout_height="wrap_content"
  10.         android:layout_x="109dp"
  11.         android:layout_y="83dp"
  12.         android:text="Button" />
  13.    
  14. </AbsoluteLayout>
复制代码
   运行结果:


    LogCat

    Console只能显示Windows下运行的平台信息,例如:模拟器的运行状态(模拟器是运行在Windows平台上的程序)。但模拟器内的程序运行状态就不能显示在Console上了,因为这些程序不是运行到Windows上,这些信息会在LogCat中显示。

    LogCat分为5个等级,依次为:error(错误)、warn(情报)、info(信息)、debug(调试)、verbose(冗余)。



    示例:为LogCat添加过滤器,便于筛选信息。

    src/cn.itcast.logcat/MainActivity.java   
  1. package cn.itcast.logcat;

  2. import android.os.Bundle;
  3. import android.app.Activity;
  4. import android.util.Log;
  5. import android.view.Menu;

  6. public class MainActivity extends Activity {

  7.     @Override
  8.     protected void onCreate(Bundle savedInstanceState) {
  9.             
  10.         String tag = "黑马程序员";
  11.             
  12.         super.onCreate(savedInstanceState);
  13.         setContentView(R.layout.activity_main);
  14.         
  15.         System.out.println("云鹤,儿童节快乐");
  16.         
  17.         //tag表示标签,msg表示正文
  18.         //下面这种写法是在日志需要长期保留时使用。
  19.         Log.v(tag, "云鹤就业薪资13000");
  20.         Log.d(tag, "云鹤就业薪资13000");
  21.         Log.i(tag, "云鹤就业薪资13000");
  22.         Log.w(tag, "云鹤就业薪资13000");
  23.         Log.e(tag, "云鹤就业薪资13000");
  24.                                 
  25.    }
  26. }
复制代码
   运行结果:



    第一步:点击加号。



    第二步:填入过滤器设置信息。
   

    第三步:进行过滤。



    在内部存储中读写文件

    Android内存:
    RAM:运行内存,相当于电脑内存。关机,数据就会丢失。
    ROM:内部存储空间,Android系统必须的存储空间,持久化保持数据,相当于电脑的硬盘。
    SD卡/USB存储器(内置在手机内):外部存储空间,对于Android系统是可有可无的,相当于移动硬盘。
   
    内部存储路径:data/data/包名文件夹/,每个包名文件夹都是一个应用的专属空间。



    示例:

    res\layout\activity_main.xml
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:paddingBottom="@dimen/activity_vertical_margin"
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"
  7.     android:paddingRight="@dimen/activity_horizontal_margin"
  8.     android:paddingTop="@dimen/activity_vertical_margin"
  9.     tools:context=".MainActivity"
  10.     android:orientation="vertical">

  11.     <EditText
  12.         android:id="@+id/et_name"
  13.         android:layout_width="match_parent"
  14.         android:layout_height="wrap_content"/>

  15.     <!-- android:inputType="textPassword"表示输入的是密码,显示时用密文代替 -->
  16.     <EditText
  17.         android:id="@+id/et_pass"
  18.         android:layout_width="match_parent"
  19.         android:layout_height="wrap_content"
  20.         android:inputType="textPassword"/>
  21.    
  22.     <RelativeLayout
  23.         android:layout_width="match_parent"
  24.         android:layout_height="wrap_content">
  25.         
  26.             <CheckBox
  27.                 android:id="@+id/cb"
  28.                 android:layout_width="wrap_content"
  29.                 android:layout_height="wrap_content"
  30.                 android:text="记住账号密码"
  31.                 android:layout_centerVertical="true"
  32.                 />
  33.             
  34.             <Button
  35.                 android:layout_width="wrap_content"
  36.                 android:layout_height="wrap_content"
  37.                 android:text="登陆"
  38.                 android:onClick="login"
  39.                 android:layout_alignParentRight="true"
  40.                 />
  41.             
  42.         </RelativeLayout>
  43.    
  44. </LinearLayout>
复制代码

    src/cn.itcast.rwinrom/MainActivity.java  
  1. package cn.itcast.rwinrom;

  2. import java.io.BufferedReader;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.FileOutputStream;
  6. import java.io.InputStreamReader;

  7. import android.app.Activity;
  8. import android.os.Bundle;
  9. import android.view.View;
  10. import android.widget.CheckBox;
  11. import android.widget.EditText;
  12. import android.widget.Toast;

  13. public class MainActivity extends Activity {

  14.     private EditText et_name;
  15.     private EditText et_pass;

  16.     @Override
  17.     protected void onCreate(Bundle savedInstanceState) {
  18.         super.onCreate(savedInstanceState);
  19.         setContentView(R.layout.activity_main);
  20.         
  21.         et_name = (EditText) findViewById(R.id.et_name);
  22.         et_pass = (EditText) findViewById(R.id.et_pass);
  23.         
  24.         readAccount();
  25.     }

  26.     public void login(View v){
  27.             
  28.             //获取用户输入的数据
  29.             String name = et_name.getText().toString();
  30.             String pass = et_pass.getText().toString();
  31.             
  32.             CheckBox cb = (CheckBox) findViewById(R.id.cb);
  33.             if(cb.isChecked()){
  34.                     File file = new File("data/data/cn.itcast.rwinrom/info.txt");
  35.                     try{
  36.                             FileOutputStream fos = new FileOutputStream(file);
  37.                             fos.write((name + "##" + pass).getBytes());
  38.                             fos.close();
  39.                     }catch(Exception e){
  40.                             e.printStackTrace();
  41.                     }
  42.             }
  43.             //弹出吐司对话框
  44.             //Activity是Context的子类
  45.             //Toast.LENGTH_LONG表示显示5秒
  46.             //Toast.LENGTH_SHORT表示显示3秒
  47.             Toast.makeText(this, "登陆成功", Toast.LENGTH_LONG).show();
  48.     }
  49.    
  50.     public void readAccount(){
  51.             File file = new File("data/data/cn.itcast.rwinrom/info.txt");
  52.             if(file.exists()){
  53.                     try{
  54.                             FileInputStream fis = new FileInputStream(file);
  55.                             //把字节流转换成字符流
  56.                             BufferedReader br = new BufferedReader(new InputStreamReader(fis));
  57.                             String text = br.readLine();
  58.                             String[] s = text.split("##");
  59.                            
  60.                             et_name.setText(s[0]);
  61.                             et_pass.setText(s[1]);
  62.                         
  63.                             fis.close();
  64.                     }catch(Exception e){
  65.                             e.printStackTrace();
  66.                     }
  67.             }
  68.     }
  69. }
复制代码
   运行结果:

    1、在模拟器上运行应用程序,输入用户名、密码,勾上记住账号密码,点击登陆。可以看到弹出吐司,登陆成功。



    2、在Android设备文件目录下,可以看到成功生成info.txt文件,点击右上角的“pull a file from the device”按钮,将info.txt提取出来,保存到桌面。



    3、打开info.txt文件,可以看到成功存入数据。



    4、重新运行应用程序,可以看到读取数据成功,用户名、密码成功显示。



    P.S.
    1、点击返回键,会摧毁当前Activity,重新点击应用图标,会重新创建Activity。
    2、点击HOME键,只会将Activity放到后台去,重新点击图标,只是重新提取出来。
    所以,上面的应用程序,即使是第一次运行,输入用户名、密码,并且不勾选“记住账户密码”。如果此时点击HOME键,Activity消失。然后,再点击应用程序图标,竟然可以看到Activity显示出了用户名、密码!然而,这根本不是回显,Activity只是暂时放到后台,然后重新提取出来罢了。
    3、在内部存储空间中读写不需要任何权限!

    使用API获取内部存储空间的路径

    如果将上面应用程序的MainActivity类中的代码进行如下修改,可以看到后台报警告。原因是不能访问其他应用程序的专属空间,只能访问自己的。





    为了防止内部存储空间不小心写错,API提供了获取内部存储空间路径的方法。修改后,代码如下:

   



    运行结果,如下:



    P.S.
    getFilesDir方法所在的类为上下文包装类,ContextWrapper。



    并且,Activity就是ContextWrapper的子类。



    所谓的上下文就是一个应用环境全局信息的接口,也就是说,通过上下文的API可以拿到应用环境的全局信息,例如:包名、版本号、内部存储等信息。
    Toast.makeText(this,"登陆成功",0).show();语句中的this就是上下文,表示吐司需要显示在哪个上下文中。
    Button bt = new Button(this);语句中的this也是上下文,表示该组件创建出来之后,显示在哪个上下文中。

    谷歌的API还提供了另一个方法获取内部存储空间路径:getCacheDir(),它返回的路径为data/data/cn.itcast.rwinrom/cache,得到的是缓存路径,也就是cache文件夹路径。修改后,代码如下:
   


    运行结果,如下:


   
    区别:
    getFilesDir方法返回的路径中的files文件夹是持久化保存数据的。
    getCacheDir方法返回的路径中的Cache文件夹是保存缓存数据的。当设备内存可用存储空间比较少时,Cache中的文件可能会被系统删除。

    在外部存储中读写文件

    SD卡路径为storage/sdcard(4.3版本),之所以还存在根目录sdcard(2.3版本之前)及mnt/sdcard(2.3版本~4.3版本),是因为早期版本的sd卡路径正是在根目录,后期移到了mnt/sdcard,为了与低版本兼容,所以现在他们还存在,其实只是快捷方式而已,指向的路径依然是storage/sdcard。



    往SD卡中写数据需要权限。而从SD卡中读取数据在4.0版本以前是不需要权限,后来谷歌在Android系统中添加了保护SD卡的选项(如下图)。如果勾选了,那么在真机上是有效的(也就是说,模拟器上是无效的)。不过,一般情况下,不勾选。因为,很多应用程序并没有申请读取SD卡的权限,一旦勾上,很多应用程序将无法读取SD卡。因此,为了向下兼容,一般不勾。



    示例:

    将上面“在内部存储中读取文件”中示例的MainActivity类中代码做一下修改,如下。





    为读写SD卡添加权限(读SD卡权限可加可不加):





    运行结果:





    检测SD卡状态

    很多手机厂商都修改了SD卡路径,因此,很多手机SD卡的路径不是storage/sdcard。但是,sdcard的快捷方式基本上都是存在的,并且指向真实的SD卡路径。因此,访问SD卡路径,可以通过获取SD卡快捷方式的方法。当然,也可以调用API中提供的相应方法获取SD卡路径:Environment.getExternalStorageDirectory()。

    P.S.
    外部存储空间对于手机来说并不一定是必须的。所以,在使用前,一定要做确认手机的SD卡是否存在。可以通过Environment.getExternalStorageState()确定SD卡的状态,此方法的常见返回值说明如下:
    MEDIA_REMOVED:sd卡被拔出。
    MEDIA_UNMOUNTED:sd卡未挂载(4.0版本以前,手机可以通过点击settings-->Storage-->Storage settings-->Unmounted SD card,使SD卡未挂载)。
    MEDIA_CHECKING:sd卡正在准备。
    MEDIA_MOUNTED:sd卡已挂载,当前可用。
    MEDIA_READ_ONLY:sd卡挂载可用,但是只读。

    示例:

    将上面“在内部存储中读取文件”中示例的MainActivity类中代码做一下修改,如下。



    运行结果:

    由于在4.0版本之前才有手动使SD卡未挂载的功能,这里使用2.3.3版本测试。

    首先,Unmounted SD card,观察效果,可以看到提示:sd不可用。




   
    然后,mounted SD card,观察效果,成功保存用户名、密码信息。





    P.S.
    当有多个模拟器运行时,想要观察某一个模拟器的文件目录,只需要在Devices选项卡中点击那个模拟器,即可在File Explorer选项卡中看到那个模拟器的文件目录。


    获取SD卡剩余容量

    当用户做下载等操作时,SD卡的空间可能不足,所以需要提前获取SD卡剩余容量,给予用户提示信息。

    在Android系统中,可以查看SD卡剩余容量,点击Setting-->Storage。



    sdk文件夹中的sources文件夹中的源码是Android jar包的源码,Android系统源码则不同,一定要区分开。如下图。



    其中,packages/apps路径为Android系统级应用程序所在的目录,可以看到settings应用程序。



    查看settings应用程序的源码

    1、导入settings应用程序到eclipse中。

         ①点击File-->New-->Other....。



        ②点击Android下的Android Project from Existing Code-->Next。



        ③点击Root Directory右侧的Browse...按钮,找到settings应用程序所在的目录,点击确定。



        ④下图中的tests为测试settings的应用程序,不勾。


        ⑤导入成功。



    P.S.
    之所以会报错,是因为普通应用开发是无法访问系统级API的(settings工程导入eclipse就成为了一个普通应用开发项目)。

    2、查找实现查看SD卡剩余空间的源码。

        ①通过搜索关键字“Available space”开始查找。



        ②通过eclipse的“File Search”在整个工作空间中搜索“Available space”。

   

        ③查找到以后,双击。





        ④再搜索“memory_available”。





        ⑤再搜索“memory_sd_avail”。





        ⑥再在本文件内搜索“MEMORY_SD_AVAIL”。



        再在本文件内搜索“mSdAvail”,可以看到,已经查找到了该段代码。



    3、解析源码。

        所有存储设备都会被划分成若干个区块,存储设备的总容量 = 每个区块大小 * 区块总数量。



        其中的formatSize函数实际上就是将得出的字节数,转换成MB、GB、TB及PB显示给用户。



    示例:我们自己写程序获取SD卡剩余容量。

    res\layout\activity_main.xml
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:paddingBottom="@dimen/activity_vertical_margin"
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"
  7.     android:paddingRight="@dimen/activity_horizontal_margin"
  8.     android:paddingTop="@dimen/activity_vertical_margin"
  9.     tools:context=".MainActivity" >

  10.     <TextView
  11.         android:id="@+id/tv"
  12.         android:layout_width="wrap_content"
  13.         android:layout_height="wrap_content"
  14.         android:text="@string/hello_world" />

  15. </RelativeLayout>
复制代码

    src/cn.itcast.getsdavail/MainActivity.java  
  1. package cn.itcast.getsdavail;

  2. import java.io.File;

  3. import android.os.Build;
  4. import android.os.Bundle;
  5. import android.os.Environment;
  6. import android.os.StatFs;
  7. import android.app.Activity;
  8. import android.text.format.Formatter;
  9. import android.view.Menu;
  10. import android.widget.TextView;

  11. public class MainActivity extends Activity {

  12.     @Override
  13.     protected void onCreate(Bundle savedInstanceState) {
  14.         super.onCreate(savedInstanceState);
  15.         setContentView(R.layout.activity_main);
  16.         
  17.         File path = Environment.getExternalStorageDirectory();
  18.         StatFs stat = new StatFs(path.getPath());
  19.         
  20.         long blockSize;
  21.         long availableBlocks;
  22.         
  23.         //下面的很多方法已经过时了,因为getBlockSize等方法的返回值都是int类型,如果设备较大,返回的blockSize数值可能超过int类型的范围,导致溢出。
  24.         //改为使用最新的getBlockSizeLong等方法返回为long类型数据即可。由于,只有<span style="line-height: 30.7999992370605px;">4.3以上版本的API才支持这些方法。</span><span style="line-height: 2.2em;">因此,最好做一下判断。</span>
复制代码
   运行结果:




    文件访问权限

    Android的文件访问权限是从Linux继承来的。



    drwxrwxrwx:
    第一个字母:如果是d,表示文件夹;如果是-,表示文件;如果是l,表示快捷方式。
    三组rwx(r(read),w(write),x(exeute,执行))表示三种不同用户的权限。
    在Android中,每个应用,都是一个独立的用户。也就是说,创建一个应用,就是创建了一个新的用户。删除一个应用,就是删除了一个用户。
    第一组rwx:描述文件拥有者(owner)对文件的权限。例如,上图中的data/cn.itcast.rwinrom/cache/info.txt文件的创建者就是拥有者,也就是cn.itcast.rwinrom应用程序。
    第二组rwx:描述与文件拥有者同一用户组(grouper)的用户对文件的权限。默认情况,各个应用程序彼此是独立的用户。可以手动设置同组用户,不过只有系统应用为了方便才会设置同组用户,我们不用管。
    第三组rwx:描述其他用户(other)对文件的权限。其他应用程序就可以称为某一个应用程序的其他用户。

    实验:其他应用程序读取当前应用程序的文件。

    res\layout\activity_main.xml
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context=".MainActivity"
  6.     android:orientation="vertical">

  7.     <Button
  8.         android:layout_width="wrap_content"
  9.         android:layout_height="wrap_content"
  10.         android:onClick="click1"
  11.         android:text="按钮一" />
  12.    
  13.     <Button
  14.         android:layout_width="wrap_content"
  15.         android:layout_height="wrap_content"
  16.         android:onClick="click2"
  17.         android:text="按钮二" />

  18. </LinearLayout>
复制代码

    src/cn.itcast.permission/MainActivity.java  
  1. package cn.itcast.permission;

  2. import java.io.FileNotFoundException;
  3. import java.io.FileOutputStream;

  4. import android.app.Activity;
  5. import android.os.Bundle;
  6. import android.view.View;

  7. public class MainActivity extends Activity {

  8.         @Override
  9.         protected void onCreate(Bundle savedInstanceState) {
  10.                 super.onCreate(savedInstanceState);
  11.                 setContentView(R.layout.activity_main);
  12.         }

  13.     public void click1(View v){
  14.             
  15.             //Android中提供的openFileOutput方法可以直接获取FileOutputStream,文件会被写在内部文件空间中(data/data/报名文件夹/files/)
  16.             try {
  17.                         //MODE_PRIVATE表示拥有者和同组用户可以读写,其他用户无法访问
  18.                         FileOutputStream fos = openFileOutput("info1.txt", MODE_PRIVATE);
  19.                         fos.write("haha".getBytes());
  20.                 } catch (Exception e) {
  21.                         e.printStackTrace();
  22.                 }
  23.     }
  24.    
  25.     public void click2(View v){
  26.             
  27.             try {
  28.                         //MODE_WORLD_READABLE表示任何用户都对其可读,MODE_WORLD_WRITEABLE表示任何用户都对其可写
  29.                         FileOutputStream fos = openFileOutput("info2.txt", MODE_WORLD_READABLE|MODE_WORLD_WRITEABLE);
  30.                         fos.write("hehe,你来读我啊".getBytes());
  31.                 } catch (Exception e) {
  32.                         e.printStackTrace();
  33.                 }        
  34.     }
  35. }
复制代码

    创建新的名为“其他用户”的应用程序,代码如下:



    res\layout\activity_main.xml
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:paddingBottom="@dimen/activity_vertical_margin"
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"
  7.     android:paddingRight="@dimen/activity_horizontal_margin"
  8.     android:paddingTop="@dimen/activity_vertical_margin"
  9.     tools:context=".MainActivity" >

  10.     <Button
  11.         android:layout_width="wrap_content"
  12.         android:layout_height="wrap_content"
  13.         android:text="读取"
  14.         android:onClick="click"/>

  15. </RelativeLayout>
复制代码

    src/cn.itcast.other/MainActivity.java  
  1. package cn.itcast.other;

  2. import java.io.BufferedReader;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.FileNotFoundException;
  6. import java.io.IOException;
  7. import java.io.InputStreamReader;

  8. import android.app.Activity;
  9. import android.os.Bundle;
  10. import android.view.View;
  11. import android.widget.Toast;

  12. public class MainActivity extends Activity {

  13.         @Override
  14.         protected void onCreate(Bundle savedInstanceState) {
  15.                 super.onCreate(savedInstanceState);
  16.                 setContentView(R.layout.activity_main);
  17.         }
  18.         
  19.         public void click(View v){
  20.                
  21.                 File file = new File("data/data/cn.itcast.permission/files","info2.txt");
  22.                
  23.                 try {
  24.                         FileInputStream fis = new FileInputStream(file);
  25.                         BufferedReader br = new BufferedReader(new InputStreamReader(fis));
  26.                         Toast.makeText(this,br.readLine(),Toast.LENGTH_LONG).show();
  27.                 } catch (Exception e) {
  28.                         e.printStackTrace();
  29.                 }
  30.         }
  31. }
复制代码
   运行结果:

    点击按钮一、按钮二,生成文件info1.txt、info2.txt。



    可以看到info1.txt为拥有者和同一用户组具备读写权限,info2.txt则为任何用户都具备读写权限。



    运行“其他用户”应用程序,点击按钮,可以看到读取info2.txt文件成功。





    SharedPreferences

    在真实开发中,类似于账号及密码保存功能等持久化保存比较零散、简单数据的情况使用SharedPerferences比较方便,它是以键值对的方式将数据存储进xml文件中。

    示例:修改保存用户登录名,密码的案例,用SharedPreferences保存数据的方式实现。

    src/cn.itcast.sharedpreference/MainActivity.java  
  1. package cn.itcast.sharedpreference;

  2. import android.app.Activity;
  3. import android.content.SharedPreferences;
  4. import android.content.SharedPreferences.Editor;
  5. import android.os.Bundle;
  6. import android.view.View;
  7. import android.widget.CheckBox;
  8. import android.widget.EditText;
  9. import android.widget.Toast;

  10. public class MainActivity extends Activity {

  11.     private EditText et_name;
  12.     private EditText et_pass;

  13.     @Override
  14.     protected void onCreate(Bundle savedInstanceState) {
  15.         super.onCreate(savedInstanceState);
  16.         setContentView(R.layout.activity_main);
  17.         
  18.         et_name = (EditText) findViewById(R.id.et_name);
  19.         et_pass = (EditText) findViewById(R.id.et_pass);
  20.             
  21.         readAccount();
  22.     }

  23.     public void login(View v){
  24.             
  25.             String name = et_name.getText().toString();
  26.             String pass = et_pass.getText().toString();
  27.             
  28.             CheckBox cb = (CheckBox) findViewById(R.id.cb);
  29.             if(cb.isChecked()){
  30.                
  31.                     //SharedPreferences是接口,通过getSharedPreferences方法获取对象,第一个参数为文件名,第二个参数控制访问权限。
  32.                     //在路径为data/data/包名文件夹/shared_prefs目录下保存生成的xml文件。
  33.                     SharedPreferences sp = getSharedPreferences("info", MODE_PRIVATE);
  34.                     
  35.                     //获取编辑器
  36.                     Editor ed = sp.edit();
  37.                     ed.putString("name", name);
  38.                     ed.putString("pass", pass);
  39.                     //提交
  40.                     ed.commit();
  41.             }
  42.             Toast.makeText(this, "登陆成功", Toast.LENGTH_LONG).show();
  43.     }
  44.    
  45.     public void readAccount(){
  46.             
  47.             SharedPreferences sp = getSharedPreferences("info", MODE_PRIVATE);
  48.    
  49.             //第二个参数表示如果没有对应第一个参数的value值返回的默认值,这里设置为空字符串。
  50.             String name = sp.getString("name", "");
  51.             String pass = sp.getString("pass", "");
  52.             
  53.             et_name.setText(name);
  54.             et_pass.setText(pass);
  55.     }
  56. }
复制代码
   运行结果:



    可以看到,数据成功保存到xml文件中。





    回显成功。



    生成xml文件

    虽然SharedPreferences可以实现保存数据到xml中,但是,对于类似于用户保存短信等Android应用程序来说还是不行的。例如,保存短信功能,需要保存内容、发送时间、接收人号码、短信类型(发送、接收)等等多种类型数据,尤其是数据组织结构比较复杂时,使用SharedPreferences会相当的麻烦。

    示例:通过xml方式保存短信。

    res\layout\activity_main.xml
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:paddingBottom="@dimen/activity_vertical_margin"
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"
  7.     android:paddingRight="@dimen/activity_horizontal_margin"
  8.     android:paddingTop="@dimen/activity_vertical_margin"
  9.     tools:context=".MainActivity" >

  10.     <Button
  11.         android:layout_width="wrap_content"
  12.         android:layout_height="wrap_content"
  13.         android:text="生成xml文件"
  14.         android:onClick="click"
  15.         />

  16. </RelativeLayout>
复制代码

    src/cn.itcast.createxml/Sms.java
  1. package cn.itcast.createxml;

  2. public class Sms {

  3.         private String body;
  4.         private String address;
  5.         private long date;
  6.         private int type;
  7.         
  8.         public String getBody() {
  9.                 return body;
  10.         }
  11.         public void setBody(String body) {
  12.                 this.body = body;
  13.         }
  14.         public String getAddress() {
  15.                 return address;
  16.         }
  17.         public void setAddress(String address) {
  18.                 this.address = address;
  19.         }
  20.         public long getDate() {
  21.                 return date;
  22.         }
  23.         public void setDate(long date) {
  24.                 this.date = date;
  25.         }
  26.         public int getType() {
  27.                 return type;
  28.         }
  29.         public void setType(int type) {
  30.                 this.type = type;
  31.         }
  32.         
  33.         public Sms(String body, String address, long date, int type) {
  34.                 super();
  35.                 this.body = body;
  36.                 this.address = address;
  37.                 this.date = date;
  38.                 this.type = type;
  39.         }
  40. }
复制代码

    src/cn.itcast.createxml/MainActivity.java  
  1. package cn.itcast.createxml;

  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. import java.io.FileOutputStream;
  5. import java.util.ArrayList;
  6. import java.util.List;

  7. import android.app.Activity;
  8. import android.os.Bundle;
  9. import android.view.View;

  10. public class MainActivity extends Activity {

  11.         List<Sms> smsList;
  12.         
  13.         @Override
  14.         protected void onCreate(Bundle savedInstanceState) {
  15.                 super.onCreate(savedInstanceState);
  16.                 setContentView(R.layout.activity_main);
  17.                
  18.                 smsList = new ArrayList<Sms>();
  19.                
  20.                 for(int i = 0; i < 10; i++){
  21.                         Sms sms = new Sms("云鹤" + i + "号","138" + i + i,System.currentTimeMillis(),1);
  22.                         smsList.add(sms);
  23.                 }
  24.         }
  25.         
  26.         public void click(View v){
  27.                
  28.                 StringBuffer sb = new StringBuffer();
  29.                
  30.                 sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
  31.                 sb.append("<smss>");
  32.                
  33.                 for(Sms sms : smsList){
  34.                         sb.append("<sms>");
  35.                         
  36.                         sb.append("<body>");
  37.                         sb.append(sms.getBody());
  38.                         sb.append("</body>");
  39.                         
  40.                         sb.append("<address>");
  41.                         sb.append(sms.getAddress());
  42.                         sb.append("</address>");
  43.                         
  44.                         sb.append("<date>");
  45.                         sb.append(sms.getDate());
  46.                         sb.append("</date>");
  47.                         
  48.                         sb.append("<type>");
  49.                         sb.append(sms.getType());
  50.                         sb.append("</type>");
  51.                         
  52.                         sb.append("</sms>");
  53.                 }
  54.                
  55.                 //备份数据的应用一般都存在外部存储空间中。因为,一旦应用程序被删,内部存储空间内的该应用程序就会被清除,而外部存储空间不会被清掉。
  56.                 File file = new File("sdcard/sms.xml");
  57.                
  58.                 try {
  59.                         FileOutputStream fos = new FileOutputStream(file);
  60.                         fos.write(sb.toString().getBytes());
  61.                         fos.close();
  62.                 } catch (Exception e) {
  63.                         e.printStackTrace();
  64.                 }
  65.         }
  66. }
复制代码
   运行结果:



    点击“生成xml文件”按钮,可以看到成功生成了sms.xml文件。





    xml序列化器

    上面拼接字符串的方法过于麻烦,Android中有一个xml序列化器可以帮助我们解决这个问题。

    示例:将上面示例中拼接字符串的方式修改为通过xml序列化器生成xml文件。

    src/cn.itcast.createxml/MainActivity.java  
  1. package cn.itcast.createxml;

  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.util.ArrayList;
  5. import java.util.List;

  6. import org.xmlpull.v1.XmlSerializer;

  7. import android.app.Activity;
  8. import android.os.Bundle;
  9. import android.util.Xml;
  10. import android.view.View;

  11. public class MainActivity extends Activity {

  12.         List<Sms> smsList;
  13.         
  14.         @Override
  15.         protected void onCreate(Bundle savedInstanceState) {
  16.                 super.onCreate(savedInstanceState);
  17.                 setContentView(R.layout.activity_main);
  18.                
  19.                 smsList = new ArrayList<Sms>();
  20.                
  21.                 for(int i = 0; i < 10; i++){
  22.                         Sms sms = new Sms("云鹤" + i + "号","138" + i + i,System.currentTimeMillis(),1);
  23.                         smsList.add(sms);
  24.                 }
  25.         }
  26.         
  27.         public void click(View v){
  28.                
  29.                 //获取xml序列化器
  30.                 XmlSerializer xs = Xml.newSerializer();
  31.                
  32.                 try{
  33.                         //初始化,指定生成的xml文件路径和文件名
  34.                         File file = new File("sdcard/sms2.xml");
  35.                         FileOutputStream fos = new FileOutputStream(file);
  36.                         //编码:xml文件使用什么编码生成
  37.                         xs.setOutput(fos,"utf-8");
  38.                         
  39.                         //开始生成xml文件
  40.                         //生成头结点
  41.                         //两个参数分别用来定义XML文件的头部<?xml version="1.0" encoding="utf-8" standalone="yes"?>中encoding和standalone的值
  42.                         xs.startDocument("utf-8", true);
  43.                         //开始节点,第一个参数为名称空间,用不到,设置为null。
  44.                         xs.startTag(null, "smss");
  45.                         
  46.                         for(Sms sms : smsList){
  47.                                 xs.startTag(null, "sms");
  48.                                 
  49.                                 xs.startTag(null, "body");
  50.                                 xs.text(sms.getBody());
  51.                                 xs.endTag(null, "body");
  52.                                 
  53.                                 xs.startTag(null, "address");
  54.                                 xs.text(sms.getAddress());
  55.                                 xs.endTag(null, "address");
  56.                                 
  57.                                 xs.startTag(null, "date");
  58.                                 xs.text(sms.getDate() + "");
  59.                                 xs.endTag(null, "date");
  60.                                 
  61.                                 xs.startTag(null, "type");
  62.                                 xs.text(sms.getType() + "");
  63.                                 xs.endTag(null, "type");
  64.                                 
  65.                                 xs.endTag(null, "sms");
  66.                         }
  67.                         
  68.                         //结束节点
  69.                         xs.endTag(null, "smss");
  70.                         
  71.                         //告知序列化器xml文件生成完毕
  72.                         xs.endDocument();
  73.                 }catch(Exception e){
  74.                         e.printStackTrace();
  75.                 }
  76.         }
  77. }
复制代码
   运行结果:

    可以看到,生成xml文件成功。





    P.S.
    使用xml序列化器生成xml文件还有一个好处,那就是会自动对特殊字符进行转义。

    示例:

    对上面示例中加上如下代码,其中“<”及“>”都是特殊字符。



    运行结果:
   
    可以看到成功生成xml文件,但是其中的特殊字符已经转义了。





~END~



~爱上海,爱黑马~



作者: guohaichang    时间: 2015-6-23 19:24
学习吧,学习了!!
作者: qian0217wei    时间: 2015-6-23 23:10
赞一个!
作者: 我是隔壁老王呀    时间: 2015-6-23 23:47
做的挺不错的,真心学习了
作者: 0618张军    时间: 2015-6-24 06:36
真心做出来的东西呀
作者: javazhang    时间: 2015-6-24 23:27
黑马真的乃是业界的一匹黑马呀,赞
作者: 聪聪那年    时间: 2015-6-26 22:16
很好的笔记

作者: langxiao505    时间: 2015-6-26 22:19
好屌!!阳哥威武~
作者: 艾维拉小叶    时间: 2015-7-6 11:27
收藏收藏
作者: 耀阳圣尊    时间: 2015-7-6 11:49
真的,这个笔记真是没谁了。
作者: 942932576    时间: 2015-7-6 16:57
不错不错,刚好可以学习
作者: xiaoxinxin003    时间: 2015-7-6 18:03
不错不错哦。。。
作者: Nemo    时间: 2015-7-6 18:08
不错不错哦
作者: fmi110    时间: 2015-7-6 19:16
还停留在java基础阶段呢
作者: ZGL360    时间: 2015-7-6 20:41
不错  加油很详细
作者: 何时归来看花开    时间: 2015-7-6 21:17
java基础刚开始学,感觉要学的真多
作者: threeforPP    时间: 2015-7-6 21:18
java基础开学完了,感觉学的迷迷糊糊的!不知道能不能考上黑马,为自己加油吧!!
作者: q953655369    时间: 2015-7-6 21:23
加油加油一定能考得上
作者: 繁华落尽    时间: 2015-7-6 21:30
生命是用来纪念的,而不是用来怀念的.加油.相信自己.
作者: 走在这里    时间: 2015-7-6 21:32
我要为自己加油
作者: 双元王志超    时间: 2015-7-6 21:46
小伙子真努力啊,笔记做这么好,有机会多多交流
作者: chytth    时间: 2015-7-6 21:54
顶顶顶,android 布局真的很重要,在几种常见的布局基础上才能玩转高级UI布局。
作者: 李玉    时间: 2015-7-6 21:55
漂亮的UI设计是一款APP的门面,很重要

作者: 安逸丶    时间: 2015-7-6 21:58
这笔记 太专业了
作者: 贺洋洋123    时间: 2015-7-6 21:59
笔记做的好 对学习很有帮助啊
作者: Miss.H    时间: 2015-7-6 22:26
很有用,很受教!!!!:D
作者: 范玉    时间: 2015-7-6 22:40
就是.上课不仅要认真听讲.也一定要好好的记笔记....好记性不如烂笔头
作者: 叫什么    时间: 2015-7-6 22:48
写的真好  有用  赞一个
作者: 18295718171    时间: 2015-7-6 22:55
做的这么好  看得出来努力啊
作者: 李金伦    时间: 2015-7-6 23:08
基础不好有些不理解
作者: Jackron    时间: 2015-7-6 23:19
每天都来学习
作者: 时光无痕    时间: 2015-7-6 23:27
每天都来
作者: 成佳裕    时间: 2015-7-6 23:36
学习学习
作者: 守门员    时间: 2015-7-7 07:03
日常学习
作者: l6781155    时间: 2015-7-7 09:05
zan~~~~~~~
作者: 乔栋    时间: 2015-7-7 09:06
日常签到。
作者: wws1214    时间: 2015-7-7 10:17
奋斗18期,
作者: 拐子    时间: 2015-7-7 10:58
哇哦 我要收藏起来
作者: nanfp    时间: 2015-7-7 11:22
很受教,给100个赞!!!
作者: 992791011    时间: 2015-7-7 11:28
赞一个,╮(╯▽╰)╭,还要九个子
作者: shero    时间: 2015-7-7 11:52
每天都来学习
作者: 々白点潜心ザ    时间: 2015-7-7 13:08
很好,赞一个~~~
作者: wh121    时间: 2015-7-7 14:45
虽然现在在学Java  好的东西还是提前把它收藏好。
作者: Nemo    时间: 2015-7-7 16:20
不错不错哦,谢谢分享
作者: 992791011    时间: 2015-7-7 17:45
如果我爱上你的笑容
作者: 紫夜灵魂    时间: 2015-7-7 18:53
基础学习中,以后多多瞻仰
作者: 小灬清新丶    时间: 2015-7-7 19:28
正在看基础视频,努力~
作者: wushenshen5180    时间: 2015-7-7 19:50
阳哥必顶!!
作者: 双元王志超    时间: 2015-7-7 21:27
哈哈。。。。。。。。。。。。。。。。。。。。。。。
作者: Jackron    时间: 2015-7-7 21:33
顶起,每天必看

作者: ssclovedan    时间: 2015-7-7 21:38
顶顶顶!!!!!!!!!!
作者: heimayili    时间: 2015-7-7 21:52
日常学习ing
作者: joerk    时间: 2015-7-7 22:04
阳哥,辛苦了,连载更新真是不容易哦,力挺阳哥!!!
作者: 半山岩    时间: 2015-7-7 22:04
看着这些代码就是爽,也希望自己尽快加入啊
作者: 范玉    时间: 2015-7-7 22:05
在大学虽然主修的是软件开发,但是我们大部分学习的是理论课,真正的课程实验让自己动手做的真的做不来,但是我不想被人家说白上了大学,所以我来到黑马学习java.....从最最基础学起,我相信在接下来的四个月里我一定会学有所成..一起加油:victory:
作者: 徐向贵    时间: 2015-7-7 22:19
看着代码感觉有点累
作者: wrnlksblk    时间: 2015-7-7 22:23
大家好啊,技术分好难搞啊!!!
作者: 喂丶你真坏    时间: 2015-7-7 22:23
慢慢努力喽
作者: 122125241    时间: 2015-7-7 22:25
- -慢慢来把
作者: 搁浅丶那份    时间: 2015-7-7 22:27
大家一起奋斗吧,希望每个人最后都能如愿
作者: GMQQ    时间: 2015-7-7 22:31
慢慢加油咯

作者: pathnet    时间: 2015-7-7 22:34
同学们加油
作者: sariel0081    时间: 2015-7-7 22:39
不错 每天路过帮顶
作者: 弃车保    时间: 2015-7-7 22:43
加油学习~~
作者: micro_hx    时间: 2015-7-7 22:46
好好学习啊。。。
作者: 贺洋洋123    时间: 2015-7-7 22:50
还没学到  刚进入基础班 希望以后能像阳哥那样认真对待学习!
作者: 小绿    时间: 2015-7-7 22:50
加油加油加油
作者: zhujunlin0108    时间: 2015-7-7 23:00
正在学基础,争取进安卓班
作者: 1木头1    时间: 2015-7-7 23:04
争取进入安卓就业班 fighting!
作者: cheng_xu_yuan_    时间: 2015-7-7 23:09
写的很好,阳哥加油
作者: X.MIKO    时间: 2015-7-7 23:20
虽然很辛苦 倒是咬咬牙坚持坚持
作者: wj456123    时间: 2015-7-7 23:29
辛苦了阳哥了,看笔记收获很大
作者: tinibuzhi    时间: 2015-7-7 23:32
来了来了                              
作者: Jackron    时间: 2015-7-7 23:36
谢谢分享了!
作者: 李金伦    时间: 2015-7-7 23:37
感谢阳 哥的笔记,给了我很大的帮助。
作者: 18295718171    时间: 2015-7-7 23:38
这么专业!佩服!
作者: 小囧    时间: 2015-7-7 23:54
犀利犀利,膜拜膜拜
作者: 々白点潜心ザ    时间: 2015-7-8 00:15
阳哥笔记,666~~~
作者: 繁华落尽    时间: 2015-7-8 07:43
赞一个,阳哥加油
作者: 蓦然回首3Y    时间: 2015-7-8 08:11
太赞了

作者: yang9876q    时间: 2015-7-8 08:42
每天一打卡
作者: ym123456    时间: 2015-7-8 08:43
每天一打卡

作者: ZGL360    时间: 2015-7-8 08:52
加油。继续更
作者: 堕落天使    时间: 2015-7-8 09:18
加油,坚持住!
作者: 吃荷包蛋    时间: 2015-7-8 10:40
加油,加油坚持住,真是造福人类啊
作者: l6781155    时间: 2015-7-8 11:32
加油~~~~~~~~~~~~~
作者: 乔栋    时间: 2015-7-8 12:11
    加油,加油坚持住,真是造福人类啊
作者: wws1214    时间: 2015-7-8 15:53
坚定信念,一路到底
作者: 陈建民1    时间: 2015-7-8 17:58
努力,加油,前途无限!
作者: 进军黑马    时间: 2015-7-8 21:25
努力吧,奔腾吧亲爱的自己!!
作者: 15311068548    时间: 2015-7-8 21:46
努力吧,加油
作者: 非文    时间: 2015-7-8 21:49
努力,一定要坚持
作者: zhangxin    时间: 2015-7-8 21:50
加油,少年,
作者: Jackron    时间: 2015-7-8 21:51
给力,加油
作者: sariel0081    时间: 2015-7-8 22:02
过来看看学习下
作者: 徐向贵    时间: 2015-7-8 22:09
我能说今天第一次及格吗
作者: 我要当大神2015    时间: 2015-7-8 22:14
看完之后能够更加熟悉各种布局的特点,会持续关注,等待更新。。。
作者: 徐向贵    时间: 2015-7-8 22:18
争取进就业班
作者: 鲁枝权双元    时间: 2015-7-8 22:23
我这是学习java第五天的夜晚了
希望可以进入黑马就业办学习android
这对我太有用处了
作者: 小灬清新丶    时间: 2015-7-8 22:28
继续努力看视频!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2