常见布局

相对布局

RelativeLayout
  • 组件默认左对齐、顶部对齐
  • 设置组件在指定组件的右边

     android:layout_toRightOf="@id/tv1"
  • 设置在指定组件的下边

    android:layout_below="@id/tv1"
  • 设置右对齐父元素

    android:layout_alignParentRight="true"
  • 设置与指定组件右对齐

     android:layout_alignRight="@id/tv1"

线性布局

LinearLayout
  • 指定各个节点的排列方向

    android:orientation="horizontal"
  • 设置右对齐

    android:layout_gravity="right"
  • 当竖直布局时,只能左右对齐和水平居中,顶部底部对齐竖直居中无效

  • 当水平布局时,只能顶部底部对齐和竖直居中
  • 使用match_parent时注意不要把其他组件顶出去
  • 线性布局非常重要的一个属性:权重

    android:layout_weight="1"
  • 权重设置的是按比例分配剩余的空间

帧布局

FrameLayout
  • 默认组件都是左对齐和顶部对齐,每个组件相当于一个div
  • 可以更改对齐方式

    android:layout_gravity="bottom"
  • 不能相对于其他组件布局

表格布局

TableLayout
  • 每个节点是一行,它的每个子节点是一列
  • 表格布局中的节点可以不设置宽高,因为设置了也无效

    • 根节点的子节点宽为匹配父元素,高为包裹内容
    • 节点的子节点宽为包裹内容,高为包裹内容
    • 以上默认属性无法修改
  • 根节点中可以设置以下属性,表示让第1列拉伸填满屏幕宽度的剩余空间

    android:stretchColumns="1"

绝对布局

AbsoluteLayout
  • 直接指定组件的x、y坐标

    android:layout_x="144dp"android:layout_y="154dp"

logcat

  • 日志信息总共分为5个等级
    • verbose
    • debug
    • info
    • warn
    • error
  • 定义过滤器方便查看
  • System.out.print输出的日志级别是info,tag是System.out
  • Android提供的日志输出api

    Log.v(TAG, "加油吧,童鞋们");Log.d(TAG, "加油吧,童鞋们");Log.i(TAG, "加油吧,童鞋们");Log.w(TAG, "加油吧,童鞋们");Log.e(TAG, "加油吧,童鞋们");

文件读写操作

  • Ram内存:运行内存,相当于电脑的内存
  • Rom内存:内部存储空间,相当于电脑的硬盘
  • sd卡:外部存储空间,相当于电脑的移动硬盘

在内部存储空间中读写文件

小例子:用户输入账号密码,勾选“记住账号密码”,点击登录按钮,登录的同时持久化保存账号和密码

1. 定义布局
2. 完成按钮的点击事件
  • 弹Toast提示用户登录成功
        Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
3. 拿到用户输入的数据
  • 判断用户是否勾选保存账号密码
        CheckBox cb = (CheckBox) findViewById(R.id.cb);        if(cb.isChecked()){            ......        }
4. 开启io流把文件写入内部存储
  • 直接开启文件输出流写数据
        //持久化保存数据            File file = new File("data/data/com.dimon.example/info.txt");            FileOutputStream fos = new FileOutputStream(file);            fos.write((name + "##" + pass).getBytes());            fos.close();
  • 读取数据前先检测文件是否存在
        if(file.exists())
  • 读取保存的数据,也是直接开文件输入流读取
        File file = new File("data/data/com.dimon.example/info.txt");        FileInputStream fis = new FileInputStream(file);        //把字节流转换成字符流        BufferedReader br = new BufferedReader(new InputStreamReader(fis));        String text = br.readLine();        String[] s = text.split("##");
  • 读取到数据之后,回显至输入框
        et_name.setText(s[0]);        et_pass.setText(s[1]);

使用路径api读写文件

  • getFilesDir()得到的file对象的路径是data/data/com.dimon.example/files
    • 存放在这个路径下的文件,只要你不删,它就一直在
  • getCacheDir()得到的file对象的路径是data/data/com.dimon.example/cache

    • 存放在这个路径下的文件,当内存不足时,有可能被删除
  • 系统管理应用界面的清除缓存,会清除cache文件夹下的东西,清除数据,会清除整个包名目录下的东西

在外部存储读写数据

sd卡的路径

  • sdcard:2.3之前的sd卡路径
  • mnt/sdcard:4.3之前的sd卡路径
  • storage/sdcard:4.3之后的sd卡路径

  • 最简单的打开sd卡的方式

        File file = new File("sdcard/info.txt");
  • 写sd卡需要权限

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  • 读sd卡,在4.0之前不需要权限,4.0之后可以设置为需要

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  • 使用api获得sd卡的真实路径,部分手机品牌会更改sd卡的路径

    Environment.getExternalStorageDirectory()
  • 判断sd卡是否准备就绪

        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))

获取sd卡剩余容量的代码

protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    File path = Environment.getExternalStorageDirectory();        StatFs stat = new StatFs(path.getPath());        long blockSize;        long totalBlocks;        long availableBlocks;        //获取当前系统版本的等级        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){           blockSize = stat.getBlockSizeLong();             totalBlocks = stat.getBlockCountLong();             availableBlocks = stat.getAvailableBlocksLong();        }        else{          blockSize = stat.getBlockSize();            totalBlocks = stat.getBlockCount();            availableBlocks = stat.getAvailableBlocks();        }        TextView tv = (TextView) findViewById(R.id.tv);        tv.setText(formatSize(availableBlocks * blockSize));//剩余容量  }  private String formatSize(long size) {        return Formatter.formatFileSize(this, size);    }

Linux文件的访问权限

  • 在Android中,每一个应用是一个独立的用户
  • 使用10个字母表示
  • drwxrwxrwx
  • 第1位:d表示文件夹,-表示文件
  • 第2-4位:rwx,表示这个文件的拥有者用户(owner)对该文件的权限
    • r:读
    • w:写
    • x:执行
  • 第5-7位:rwx,表示跟文件拥有者用户同组的用户(grouper)对该文件的权限
  • 第8-10位:rwx,表示其他用户组的用户(other)对该文件的权限

openFileOutput的四种模式

  • MODE_PRIVATE:-rw-rw—-
  • MODE_APPEND:-rw-rw—-
  • MODE_WORLD_WRITEABLE:-rw-rw–w-
  • MODE_WORLD_READABLE:-rw-rw-r–

SharedPreference

用SharedPreference存储账号密码

  • 往SharedPreference里写数据
        //拿到一个SharedPreference对象        SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);        //拿到编辑器        Editor ed = sp.edit();        //写数据        ed.putBoolean("name", name);        ed.commit();
  • 从SharedPreference里取数据
        SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);        //从SharedPreference里取数据        String name = sp.getBoolean("name", "");

生成XML文件备份短信

  • 创建几个虚拟的短信对象,存在list中
  • 备份数据通常都是备份至sd卡

使用StringBuffer拼接字符串

  • 把整个xml文件所有节点append到sb对象里
        sb.append("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>");        //添加smss的开始节点        sb.append("<smss>");        .......
  • 把sb写到输出流中
        fos.write(sb.toString().getBytes());

使用XMl序列化器生成xml文件

  • 得到xml序列化器对象
        XmlSerializer xs = Xml.newSerializer();
  • 给序列化器设置输出流
        File file = new File(Environment.getExternalStorageDirectory(), "backupsms.xml");        FileOutputStream fos = new FileOutputStream(file);        //给序列化器指定好输出流        xs.setOutput(fos, "utf-8");//enconding:指定用什么编码生成xml文件
  • 开始生成xml文件
        //enconding:指定头结点中的enconding属性的值        xs.startDocument("utf-8", true);        xs.startTag(null, "smss");        ......        xs.endTag(null, "smss");        //告诉序列化器,文件生成完毕        xs.endDocument();

pull解析xml文件

  • 先自己写一个xml文件,存一些天气信息

拿到xml文件

        InputStream is = getClassLoader().getResourceAsStream("weather.xml");

拿到pull解析器

        XmlPullParser xp = Xml.newPullParser();

开始解析

  • 拿到指针所在当前节点的事件类型
        int type = xp.getEventType();
  • 事件类型主要有五种

    • START_DOCUMENT:xml头的事件类型
    • END_DOCUMENT:xml尾的事件类型
    • START_TAG:开始节点的事件类型
    • END_TAG:结束节点的事件类型
    • TEXT:文本节点的事件类型
  • 如果获取到的事件类型不是END_DOCUMENT,就说明解析还没有完成,如果是,解析完成,while循环结束

        while(type != XmlPullParser.END_DOCUMENT)
  • 当我们解析到不同节点时,需要进行不同的操作,所以判断一下当前节点的name
    • 当解析到weather的开始节点时,new出list
    • 当解析到city的开始节点时,创建city对象,创建对象是为了更方便的保存即将解析到的文本
    • 当解析到name开始节点时,获取下一个节点的文本内容,temp、pm也是一样
            case XmlPullParser.START_TAG:            //获取当前节点的名字                if("weather".equals(xp.getName())){                    citys = new ArrayList<City>();                }                else if("city".equals(xp.getName())){                    city = new City();                }                else if("name".equals(xp.getName())){                    //获取当前节点的下一个节点的文本                    String name = xp.nextText();                    city.setName(name);                }                else if("temp".equals(xp.getName())){                    String temp = xp.nextText();                    city.setTemp(temp);                }                else if("pm".equals(xp.getName())){                    String pm = xp.nextText();                    city.setPm(pm);                }                break;
  • 当解析到city的结束节点时,说明city的三个子节点已经全部解析完了,把city对象添加至list
        case XmlPullParser.END_TAG:            if("city".equals(xp.getName())){                    citys.add(city);            }

换行符也是文本节点

SQLite数据库

  • 轻量级关系型数据库
  • 创建数据库需要使用的api:SQLiteOpenHelper
            //arg1:数据库文件的名字            //arg2:游标工厂            //arg3:数据库版本            public MyOpenHelper(Context context, String name, CursorFactory factory, int version){}

必须定义一个构造方法:
数据库被创建时会调用:onCreate方法
数据库升级时会调用:onUpgrade方法

创建数据库

    //创建OpenHelper对象    MyOpenHelper oh = new MyOpenHelper(getContext(), "person.db", null, 1);    //获得数据库对象,如果数据库不存在,先创建数据库,后获得,如果存在,则直接获得    SQLiteDatabase db = oh.getWritableDatabase();
  • getWritableDatabase():打开可读写的数据库
  • getReadableDatabase():在磁盘空间不足时打开只读数据库,否则打开可读写数据库
  • 在创建数据库时创建表
        public void onCreate(SQLiteDatabase db) {            // TODO Auto-generated method stub            db.execSQL("create table person (_id integer primary key autoincrement, name char(10), phone char(20), money integer(20))");        }

数据库的增删改查

SQL语句

  • insert into person (name, phone, money) values (‘张三’, ‘159874611’, 2000);
  • delete from person where name = ‘李四’ and _id = 4;
  • update person set money = 6000 where name = ‘李四’;
  • select name, phone from person where name = ‘张三’;

执行SQL语句实现增删改查

        //插入        db.execSQL("insert into person (name, phone, money) values (?, ?, ?);", new Object[]{"张三", 15987461, 75000});        //查找        Cursor cs = db.rawQuery("select _id, name, money from person where name = ?;", new String[]{"张三"});
  • 测试方法执行前会调用此方法
        protected void setUp() throws Exception {            super.setUp();            // 获取虚拟上下文对象            oh = new MyOpenHelper(getContext(), "people.db", null, 1);        }

使用api实现增删改查

  • 插入
        //以键值对的形式保存要存入数据库的数据        ContentValues cv = new ContentValues();        cv.put("name", "王陆");        cv.put("phone", 1651646);        cv.put("money", 3500);        //返回值是改行的主键,如果出错返回-1        long i = db.insert("person", null, cv);
  • 删除
        //返回值是删除的行数        int i = db.delete("person", "_id = ? and name = ?", new String[]{"1", "张三"});
  • 修改
        ContentValues cv = new ContentValues();        cv.put("money", 25000);        int i = db.update("person", cv, "name = ?", new String[]{"赵四"});
  • 查询
        //arg1:要查询的字段        //arg2:查询条件        //arg3:填充查询条件的占位符        Cursor cs = db.query("person", new String[]{"name", "money"}, "name = ?", new String[]{"张三"}, null, null, null);        while(cs.moveToNext()){            // 获取指定列的索引值            String name = cs.getString(cs.getColumnIndex("name"));            String money = cs.getString(cs.getColumnIndex("money"));            System.out.println(name + ";" + money);        }

事务

  • 保证多条SQL语句要么同时成功,要么同时失败
  • 最常见案例:银行转账
  • 事务api
        try {            //开启事务            db.beginTransaction();            ...........            //设置事务执行成功            db.setTransactionSuccessful();        } finally{            //关闭事务            //如果此时已经设置事务执行成功,则sql语句生效,否则不生效            db.endTransaction();        }

把数据库的数据显示至屏幕

  1. 任意插入一些数据
    • 定义业务bean:Person.java
    • 读取数据库的所有数据
        Cursor cs = db.query("person", null, null, null, null, null, null);        while(cs.moveToNext()){            String name = cs.getString(cs.getColumnIndex("name"));            String phone = cs.getString(cs.getColumnIndex("phone"));            String money = cs.getString(cs.getColumnIndex("money"));            //把读到的数据封装至Person对象            Person p = new Person(name, phone, money);            //把person对象保存至集合中            people.add(p);        }
  • 把集合中的数据显示至屏幕
         LinearLayout ll = (LinearLayout) findViewById(R.id.ll);         for(Person p : people){             //创建TextView,每条数据用一个文本框显示             TextView tv = new TextView(this);             tv.setText(p.toString());             //把文本框设置为ll的子节点             ll.addView(tv);         }

添加ScrollView使得滑动

<ScrollView>......</ScrollView>
  • 分页查询
        Cursor cs = db.query("person", null, null, null, null, null, null, "0, 10");

ListView

  • 就是用来显示一行一行的条目的
  • MVC结构
    • M:model模型层,要显示的数据 javaBean ————people集合
    • V:view视图层,用户看到的界面 jsp ————ListView
    • c:control控制层,操作数据如何显示 servlet ————adapter对象
  • 每一个条目(Item)都是一个View对象

BaseAdapter

  • 必须实现的两个方法

第一个

            //系统调用此方法,用来获知模型层有多少条数据            @Override            public int getCount() {                return people.size();            }

第二个:position:是return的View对象所对应的数据在集合中的位置

            //系统调用此方法,获取要显示至ListView的View对象            //position:是return的View对象所对应的数据在集合中的位置      //position:本次getView方法调用所返回的view对象,在listView中是处于第几个条目,那么position的值就是多少            @Override            public View getView(int position, View convertView, ViewGroup parent) {                System.out.println("getView方法调用" + position);                TextView tv = new TextView(MainActivity.this);                //拿到集合中的元素                Person p = people.get(position);                tv.setText(p.toString());                //把TextView的对象返回出去,它会变成ListView的条目                return tv;            }
  • 屏幕上能显示多少个条目,getView方法就会被调用多少次,屏幕向下滑动时,getView会继续被调用,创建更多的View对象显示至屏幕

条目的缓存

  • 当条目划出屏幕时,系统会把该条目缓存至内存,当该条目再次进入屏幕,系统在重新调用getView时会把缓存的条目作为convertView参数传入,但是传入的条目不一定是之前被缓存的该条目,即系统有可能在调用getView方法获取第一个条目时,传入任意一个条目的缓存

提升ListView的运行效率

public class NewsAdapter extends ArrayAdapter<News> {    private int resourceId;    public NewsAdapter(Context context, int textViewResourceId, List<News> objects) {        super(context, textViewResourceId, objects);        resourceId = textViewResourceId;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        News news = getItem(position);        View view;        ViewHolder viewHolder;        if (convertView == null) {            view = LayoutInflater.from(getContext()).inflate(resourceId, null);            viewHolder = new ViewHolder();            viewHolder.newsTitleText = (TextView) view.findViewById(R.id.news_title);            view.setTag(viewHolder);//将ViewHolder存储在View中        } else {            view = convertView;            viewHolder = (ViewHolder) view.getTag();//重新获取ViewHolder        }        //TextView newsTitleText = (TextView) view.findViewById(R.id.news_title);        viewHolder.newsTitleText.setText(news.getTitle());        return view;    }    class ViewHolder {      TextView newsTitleText;    }}

对话框

确定取消对话框

  • 创建对话框构建器对象,类似工厂模式
        AlertDialog.Builder builder = new Builder(this);
  • 设置标题和正文
        builder.setTitle("警告");        builder.setMessage("愤怒香蕉更新啦!!");
  • 设置确定和取消按钮
        builder.setPositiveButton("马上去水一贴", new OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                // TODO Auto-generated method stub                Toast.makeText(MainActivity.this, "恭喜你水贴成功,现在程序退出", 0).show();            }        });        builder.setNegativeButton("下次再说", new OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                // TODO Auto-generated method stub                Toast.makeText(MainActivity.this, "蕉姐这肥羊可以宰了呀", 0).show();            }        });
  • 使用构建器创建出对话框对象
        AlertDialog ad = builder.create();        ad.show();

单选对话框

        AlertDialog.Builder builder = new Builder(this);        builder.setTitle("选择你的性别");
  • 定义单选选项
        final String[] items = new String[]{                "男", "女", "其他"        };        //-1表示没有默认选择        //点击侦听的导包要注意别导错        builder.setSingleChoiceItems(items, -1, new OnClickListener() {            //which表示点击的是哪一个选项            @Override            public void onClick(DialogInterface dialog, int which) {                Toast.makeText(MainActivity.this, "您选择了" + items[which], 0).show();                //对话框消失                dialog.dismiss();            }        });        builder.show();

多选对话框

        AlertDialog.Builder builder = new Builder(this);        builder.setTitle("请选择你欲修炼之功法");
  • 定义多选的选项,因为可以多选,所以需要一个boolean数组来记录哪些选项被选了
        final String[] items = new String[]{                "无相神功",                "仰望星空",                "千年杀",                "龙阳神功"        };        //true表示对应位置的选项被选了        final boolean[] checkedItems = new boolean[]{                true,                false,                false,                false,        };        builder.setMultiChoiceItems(items, checkedItems, new OnMultiChoiceClickListener() {            //点击某个选项,如果该选项之前没被选择,那么此时isChecked的值为true            @Override            public void onClick(DialogInterface dialog, int which, boolean isChecked) {                checkedItems[which] = isChecked;            }        });        builder.setPositiveButton("确定", new OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                StringBuffer sb = new StringBuffer();                for(int i = 0;i < items.length; i++){                    sb.append(checkedItems[i] ? items[i] + " " : "");                }                Toast.makeText(MainActivity.this, sb.toString(), 0).show();            }        });        builder.show();

将这些零碎的知识点笔记整理出来,方便以后查找翻看。(^__^) 谢谢阅读~

更多相关文章

  1. android实现服务器图片本地缓存
  2. Android开发从入门到精通(项目案例版)——第一天(2019.11.29)
  3. android 设置布局动画
  4. Android(安卓)Debug certificate expired
  5. Android(安卓)使用iperf测试wifi吞吐量
  6. Android创建和使用数据库详细指南
  7. Android——SharedPreferences
  8. android listview继承BaseAdapter,自定义的适配器,getView方法执
  9. 让Ubuntu和Android同时运行(Ubuntu on Android)

随机推荐

  1. android OKHttp的基本使用详解
  2. Android清单AndroidManifest详细说明
  3. listview背景选择
  4. [置顶] Android(安卓)CardView简单使用方
  5. Android ButterKnife注解框架使用
  6. 01 Android应用的构成
  7. Android(安卓)获取闹钟引发的血案
  8. Android摇一摇功能的实现
  9. Android(安卓)ScrollView截图和图片保存
  10. Android Style与Theme .