开发项目中学到的东西

1:谷歌自带的底部按钮最多只支持5个item
2:自己的那个解决scrollview和listview滑动冲突的方法有错了,代码应该如下:

 ListAdapter listAdapter = listView.getAdapter();
        if(listAdapter != null) {
            int totalHeight = 0;
            int params = 0;
            for(int len = listAdapter.getCount(); params < len; ++params) {
                View listItem = listAdapter.getView(params, (View)null, listView);
                listItem.measure(0, 0);
                totalHeight += listItem.getMeasuredHeight();
            }
            ViewGroup.LayoutParams var6 = listView.getLayoutParams();
            var6.height = totalHeight + listView.getDividerHeight() * (listAdapter.getCount() - 1);
            listView.setLayoutParams(var6);

就是把1300去掉
3:一个圆形图片库
添加如下依赖:compile "de.hdodenhof:circleimageview:2.1.0"
示例如下:



    
    

这里必须用framelayout才能使圆形头像图片位于背景之上
4:一个漂亮的cardview布局,由多种布局共同构造出来的,代码如下:




    

        

            

                

                    

                        

                        
                    

                    

                        

                        
                    
                

                

                

                    

                    
                
            
        

        

            

                

                
            
        
    

再来一个漂亮的cardview的布局,代码如下:




    

        

            

            
        

        
    

5:可以通过对appbarlayout的滑动监听来控制floatingactionbutton的出现和消失,代码片段如下:

...
 appBarLayout.addOnOffsetChangedListener(this);

    }

    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
        if (verticalOffset == 0) {
            floatingActionButton.show();
        } else {
            floatingActionButton.hide();
        }
    }
...

xml代码如下:





    
        
    

    
            

6:android中颜色可以是8位16进制数,也可以是6位16进制数,区别就是8位的前两位是透明度的值,后6位是rgb的值,有的还是3位16进制数,这个3位的没百度到,记得做完项目之后百度

7:几个drawable中的文件,自己总结一下,代码如下


//shape设置外形
    //solid设置实心,及其颜色
    //corners设置四个角的度数



    //stroke设置空心,及其颜色和宽度
    

我的电脑的E:\Project_Model\app\src\main\res\drawable路径下有大量的文件形式的drawable,欢迎参考

8:是时候好好研究一下style.xml文件中的值了
E:\Project_Model\app\src\main\res\values路径下的styles.xml,E:\siruanbei\app\src\main\res\values路径下的styles.xml(这个里面还可以直接给主题设置背景了)欢迎参考

9:一个漂亮的登陆页面,及注册账号,忘记密码,具体在E:\Project_Model\app\src\main\res\layout下的activity_login.xml,activity_forget.xml,activity_register.xml,代码如下



    

        


        

            

            

            


            

            
        


        


    

    

    

    

        

        


    

    

        

        
    

    

    

        

        
    

    

    

        

        
    

    

    

        

        

        

10:不在value文件夹下的color的值,在color文件夹下的以文件形式存在的color的值,研究一下,具体在E:\Project_Model\app\src\main\res\color

11:一个动画库,添加如下依赖,这两个依赖是共同使用的,因为一个库中用到了另外一个库中的东西:
compile 'com.daimajia.androidanimations:library:1.1.3@aar'
compile 'com.nineoldandroids:library:2.4.0'
示例如下:

YoYo.with(Techniques.Shake).duration(700).playOn(layAccPw);//其中layAccPw是要使用动画的view

12:一个实现城市三级联动的view库,地址为https://github.com/open-android/CityPickerWebView,这个库是拿js写的,还是用https://github.com/Bigkoo/Android-PickerView这个吧,依赖为:compile 'com.contrarywind:Android-PickerView:3.2.7',这个也能实现一样的效果,而且功能更加强大,还是日期选择之类的。

13:RetrofitUtils库,网址为https://github.com/open-android/RetrofitUtils,这个框架只能上传文件和从服务器获取数据,不能通过post上传数据到服务器,并且不能返回数据到客户端,不能了解服务器端的接收情况,很伤
我自己的示例如下:

get方式
ItheimaHttp.getAsync("", new HttpResponseListener() {//注意这个范型必须是String才行,如果是object会报错
                    @Override
                    public void onResponse(String o) {
                        Log.i("xinxi", "onResponseduidele: "+o);
                        Toast.makeText(RegisterActivity.this, ""+o, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onFailure(Call call, Throwable e) {
                        super.onFailure(call, e);
                        Log.i("xinxi", "onResponse: "+e+call.toString());
                    }
                });
以下是post方式,注意了postAsync方法虽说是post方式,但是它不能携带数据
ItheimaHttp.postAsync("", new HttpResponseListener() {
                    @Override
                    public void onResponse(String o) {
                        Log.i("xinxi", "onResponseduidele: "+o);
                        Toast.makeText(RegisterActivity.this, ""+o, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onFailure(Call call, Throwable e) {
                        super.onFailure(call, e);
                        Log.i("xinxi", "onResponse: "+e+call.toString());
                    }
                });

14:注意了耗时较长的操作千万不敢放在主线程中,比如

HttpUtil.sendPostRequest("http://39.107.104.102:8080/",map,"GBK");就这句代码,我当时放在主线程中,这是一个网络请求的代码,,这个方法是返回一个String类型的数据了,但是当时就是啥也没有返回,最后放在子线程中,才打印出了数据,当一个操作耗时较长时,系统将会放弃操作他,谨记

15:这个是java中的知识,将一个字符串快速写入文件的方式,用的是PrintStream

<%
            if (request.getParameter("mima") != null) {
                request.setCharacterEncoding("UTF-8");
                File f=new File("C:\\Users\\liang\\Workspaces\\MyEclipse 8.5\\fuwuduan\\WebRoot\\log.txt");
                FileOutputStream ff=new FileOutputStream(f);
                PrintStream p=new PrintStream(ff); 
                System.out.println(request.getCharacterEncoding());
                p.write(request.getParameter("mima").getBytes("gbk"));
                ff.close();
                p.close();
                System.out.println(request.getParameter("mima"));
                zhuce = request.getParameter("mima").split(",");
                try {
                    Class.forName(driver);
                    Connection conn = DriverManager.getConnection(url, user,
                            password);
                    if (!conn.isClosed())
                        System.out.println("连接数据库成功");
                    Statement statement = conn.createStatement();
                    String sql = null;
                    System.out.println("zhuce[0]为" + zhuce[0]);
                    if (zhuce[0].equals(String.valueOf(0))) {
                        sql = "insert into guanliyuan values ('" + zhuce[1]
                                + "','" + zhuce[2] + "','" + zhuce[3] + "');";
                    } else if (zhuce[0].equals(String.valueOf(1))) {
                        sql = "insert into laoshi values ('" + zhuce[1] + "','"
                                + zhuce[2] + "','" + zhuce[3] + "');";
                    } else if (zhuce[0].equals(String.valueOf(2))) {
                        sql = "insert into xuesheng values ('" + zhuce[1]
                                + "','" + zhuce[2] + "','" + zhuce[3] + "');";
                    }
                    statement.execute(sql);
                    System.out.println("-----------------");
                    conn.close();
                } catch (ClassNotFoundException e) {
                    System.out.println("找不到驱动");
                    e.printStackTrace();
                } catch (SQLException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        %>

16:通过点击一个view来强制隐藏软键盘

 public void onClick(View v) {
        hideSoft(v);
    }
 public void hideSoft(View view)
    {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

博客如下:http://blog.csdn.net/h7870181/article/details/8332991

17:解决Error:Failed to resolve: com.android.support:support-annotations:26.0.1 错误的方法
在build.gradle的顶部加上
configurations.all {
resolutionStrategy.force 'com.android.support:support-annotations:23.1.0'
}
参考来自http://blog.csdn.net/pyfysf/article/details/77894331

18:android的数据库框架DBFlow
首先添加如下依赖 compile 'com.github.Raizlabs.DBFlow:dbflow:4.2.4'

19:litepal框架的补充

 Cursor cursor = DataSupport.findBySQL("select * from UserXinXi where name=?", view.loadData().getName());
                        while (cursor.moveToNext()){
                            Log.i("xinxing", cursor.getString(cursor.getColumnIndex("biaoshi")));
                        }
update的用法,和以前的不一样了
 ContentValues contentValues = new ContentValues();
                        contentValues.put("title", wenZiRenWuModel.getWenZiRenWuGuanLiModel().getTitle());
                        contentValues.put("content", wenZiRenWuModel.getWenZiRenWuGuanLiModel().getContent());
                        contentValues.put("time", new SimpleDateFormat("MM月dd日HH:mm:ss").format(new Date(System.currentTimeMillis())));
                        contentValues.put("jiezhitime", wenZiRenWuModel.getWenZiRenWuGuanLiModel().getJieZhiTime());
                        int i = DataSupport.updateAll(WenZiRenWu.class, contentValues, "time=?", wenZiRenWuModel.getAgeTime());

20:rxjava的链式写法,就我最近的那个项目里面有很多

  Observable observable = Observable.just("http://39.107.104.102:8080/").observeOn(Schedulers.newThread())
                .map(new Function() {
                    String ss;
                    @Override
                    public String apply(String s) throws Exception {
                        Map map = new ArrayMap<>();
                        map.put("mima", view.loadData().toString());
                        try {
                            ss = HttpUtils.sendPostRequest(s, map, "UTF-8");
                            Log.i("xinxi", "onNext: " + ss);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return ss;
                    }
                }).observeOn(AndroidSchedulers.mainThread()).map(new Function() {
                    String biaoji;
                    @Override
                    public String apply(String s) throws Exception {
                        if (s.equals("xinxi=chenggong")) {
                            view.zhuCheSuccess();
                            biaoji = "0";
                        } else {
                            view.zhuCheFail();
                            biaoji = "1";
                        }
                        return biaoji;
                    }
                }).observeOn(Schedulers.newThread()).map(new Function() {
                    boolean b;
                    @Override
                    public String apply(String s) throws Exception {
                        if(s.equals("0")){
                            UserXinXi userXinXi=new UserXinXi();
                            userXinXi.setBiaoshi(view.loadData().getBiaoshi());
                            userXinXi.setName(view.loadData().getName());
                            b=userXinXi.save();
                            Log.i("xinxi", "biaoShi.save(): "+b);
                        }
                        return b+"";
                    }
                }).observeOn(AndroidSchedulers.mainThread());
        Observer observer = new Observer() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String value) {
                Toast.makeText((Context)view, value, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        };
        observable.subscribe(observer);

比如

 Observable.just("http://39.107.104.102:8080/").observeOn(Schedulers.newThread())
                .map(new Function() {
                    String ss;
                    @Override
                    public String apply(String s) throws Exception {
                        Map map = new ArrayMap<>();
                        map.put("mima", view.loadData().toString());
                        try {
                            ss = HttpUtils.sendPostRequest(s, map, "UTF-8");
                            Log.i("xinxi", "onNext: " + ss);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return ss;
                    }
                }).observeOn(AndroidSchedulers.mainThread()).map(new Function() {
                
                    @Override
                    public String apply(String s) throws Exception {
                        if (s.equals("xinxi=chenggong")) {
                            view.zhuCheSuccess();
                        } else {
                            view.zhuCheFail();
                        }
                        return "";
                    }
                }).subscribe();

以下代码中用到了range,我以为会重复添加,其实不是,只是日志是那样打印的,实际上list中的数据没有那样重复添加,让日志给迷糊了,发射的事件都是一个做完,另外一个才开始做的,上一个并不会重复做,脑子不在线啊

 public void loadData() {
        list = new ArrayList<>();
        Observable.range(1, 7).observeOn(Schedulers.newThread()).map(new Function>() {
            Document documents;
            JiaoYuNewsModel jiaoYuNewsModel;

            @Override
            public List apply(Integer integer) throws Exception {
                Log.i("apply", "apply: " + integer);
                try {
                    documents = Jsoup.connect("http://edu.people.com.cn/GB/227057/index" + integer + ".html").get();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Elements elements = documents.select("li");
                Log.i("xia", "run: " + elements.size());
                for (Element element : elements) {
                    if ((element.text().contains("-")) && (!element.select("li>a[href]").contains("http"))) {
                        Log.i("JiaoYuNews", element.select("li>a").text() + "~~" + element.select("li>em").text() + "~~" + element.select("li>a").attr("href") + "\n");
                        jiaoYuNewsModel = new JiaoYuNewsModel();
                        jiaoYuNewsModel.setTitle(element.select("li>a").text());
                        jiaoYuNewsModel.setDate(element.select("li>em").text());
                        jiaoYuNewsModel.setWangzhi(element.select("li>a").attr("href"));
                        list.add(jiaoYuNewsModel);
                    }
                }
                return list;
            }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer>() {
            @Override
            public void accept(List list) throws Exception {
                for (JiaoYuNewsModel j : list) {
                    Log.i("dedaode", j.getTitle());
                }
            }
        });
    }

flatMap的用法,一对多,多对一,多对多

 Observable.range(1, 7).observeOn(Schedulers.newThread()).flatMap(new Function>() {
            Document documents;
            JiaoYuNewsModel jiaoYuNewsModel;

            @Override
            public ObservableSource apply(Integer integer) throws Exception {
                try {
                    documents = Jsoup.connect("http://edu.people.com.cn/GB/227057/index" + integer + ".html").get();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Elements elements = documents.select("li");
                for (Element element : elements) {
                    if ((element.text().contains("-")) && (!element.select("li>a[href]").contains("http"))) {
                        Log.i("JiaoYuNews", element.select("li>a").text() + "~~" + element.select("li>em").text() + "~~" + element.select("li>a").attr("href") + "\n");
                        jiaoYuNewsModel = new JiaoYuNewsModel();
                        jiaoYuNewsModel.setTitle(element.select("li>a").text());
                        jiaoYuNewsModel.setDate(element.select("li>em").text());
                        jiaoYuNewsModel.setWangzhi(element.select("li>a").attr("href"));
                        jiaoYuNewsModel.setI(integer);
                        list.add(jiaoYuNewsModel);
                    }
                }
                return Observable.fromIterable(list);//然后返回的这个Observable就会发射出它列表中的JiaoYuNewsModel,然后通过subscribe进行消费
            }
        }).subscribe(new Consumer() {
            @Override
            public void accept(JiaoYuNewsModel jiaoYuNewsModel) throws Exception {
            
            }
        });

下面这个才是最终版,通过flatmap正确的,就是多了个把list.clear()

 Observable.range(1, 7).observeOn(Schedulers.newThread()).flatMap(new Function>() {
            Document documents;
            JiaoYuNewsModel jiaoYuNewsModel;

            @Override
            public ObservableSource apply(Integer integer) throws Exception {
                try {
                    documents = Jsoup.connect("http://edu.people.com.cn/GB/227057/index" + integer + ".html").get();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Elements elements = documents.select("li");
                list.clear();
                for (Element element : elements) {
                    if ((element.text().contains("-")) && (!element.select("li>a[href]").contains("http"))) {
                        Log.i("JiaoYuNews", element.select("li>a").text() + "~~" + element.select("li>em").text() + "~~" + element.select
                                ("li>a").attr("href") + "\n");
                        jiaoYuNewsModel = new JiaoYuNewsModel();
                        jiaoYuNewsModel.setTitle(element.select("li>a").text());
                        jiaoYuNewsModel.setDate(element.select("li>em").text());
                        jiaoYuNewsModel.setWangzhi(element.select("li>a").attr("href"));
                        jiaoYuNewsModel.setI(integer);
                        list.add(jiaoYuNewsModel);
                    }
                }
                return Observable.fromIterable(list);
            }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer() {
            @Override
            public void accept(JiaoYuNewsModel jiaoYuNewsModel) throws Exception {
                view.showList(jiaoYuNewsModel);
            }
        });

map和flatmap的连用

 Observable.just("select * from ZuiJinJiLu").observeOn(Schedulers.newThread())
                .map(new Function() {
                    @Override
                    public Cursor apply(String s) throws Exception {
                        Cursor cursor = DataSupport.findBySQL(s);
                        return cursor;
                    }
                }).flatMap(new Function>() {
            List list = new ArrayList<>();

            @Override
            public ObservableSource apply(Cursor cursor) throws Exception {
                while (cursor.moveToNext()) {
                    ZuiJinJiLuModel zuiJinJiLuModel=new ZuiJinJiLuModel();
                    Log.i("shuju",cursor.getString(cursor.getColumnIndex("title"))+","+
                            cursor.getString(cursor.getColumnIndex("href"))+","+
                            cursor.getString(cursor.getColumnIndex("time")));
                    zuiJinJiLuModel.setTitle(cursor.getString(cursor.getColumnIndex("title")));
                    zuiJinJiLuModel.setHref(cursor.getString(cursor.getColumnIndex("href")));
                    zuiJinJiLuModel.setTime(cursor.getString(cursor.getColumnIndex("time")));
                    list.add(zuiJinJiLuModel);
                }
                return Observable.fromIterable(list);
            }
                }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer() {
            @Override
            public void accept(ZuiJinJiLuModel zuiJinJiLuModel) throws Exception {
                view.tianChongData(zuiJinJiLuModel);
            }
        });

不带参数的rxjava

  Observable.just("").observeOn(Schedulers.newThread())
                .map(new Function() {
                    @Override
                    public Bitmap apply(String s) throws Exception {
                        //int i=HttpUtil.downloadFile("http://192.168.43.24:8032/fuwuduan/downloadtouxiang.jsp","/storage/emulated/0","a"+".jpg");
                        InputStream inputStream=HttpUtil.getInputStreamFromUrl("http://192.168.43.24:8032/fuwuduan/downloadtouxiang.jsp");
                        Bitmap bitmap=ConvertUtils.bytes2Bitmap(ConvertUtils.inputStream2Bytes(inputStream));
                        //Log.d("liu", ConvertUtils.inputStream2String(inputStream, "UTF-8"));
                        return bitmap;
                    }
                }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer() {
            @Override
            public void accept(Bitmap bitmap) throws Exception {
                view.huanHead(bitmap);
            }
        });

再来一例:写入数据库

  public void writeDatabase(String shoujihao) {
        Observable.just(shoujihao).observeOn(Schedulers.newThread())
                .subscribe(new Consumer() {
                    @Override
                    public void accept(String s) throws Exception {
                        XiaLaLiShiJiLu xiaLaLiShiJiLu = new XiaLaLiShiJiLu(s);
                        xiaLaLiShiJiLu.save();
                    }
                });
    }

timer的使用

Observable.timer(1, TimeUnit.SECONDS)//不加observeOn切换线程的话,默认是在主线程中等待一秒,因为由于网络读取的时间要比读取本地数据库的时间要长,这时如果显示本地数据库的信息的话,会出现误差,因为我写的逻辑是服务器已经删了部分信息后,还要删除本地数据库的信息,由于网络读取的时间比较长,因此本地数据库还没有来得及更新,所以要延迟1秒在读取本地数据库,这样数据就更加可靠了。
                                .subscribe(new Consumer() {
                                               @Override
                                               public void accept(Long aLong) throws Exception {
                                                   renWuGuanLiPresenter.jiaZaiWenZiData();//这两个方法是1秒之后才会执行的
                                                   renWuGuanLiPresenter.isFirst();
                                               }
                                           }
                                );

filter的使用,筛选已经点评了的任务的信息

 Observable.just("http://39.107.104.102:8080/studentwenzirenwu.jsp").observeOn(Schedulers.newThread())
                .map(new Function() {
                    Map map=new ArrayMap();
                    @Override
                    public String apply(String s) throws Exception {
                        map.put("get",user);
                        String response = HttpUtils.postResponse(s,map,"UTF-8");
                        return response;
                    }
                }).flatMap(new Function>() {
            @Override
            public ObservableSource apply(String s) throws Exception {
                Gson gson = new Gson();
                if (s.equals("sendText error!")) {
                    return Observable.just("出错");
                } else if (s.contains("answer")) {
                    List list = gson.fromJson(s, new TypeToken>() {
                    }.getType());
                    return Observable.fromIterable(list);
                } else {
                    return Observable.just("为空");
                }
            }
        }).filter(new Predicate() {
            @Override
            public boolean test(Object o) throws Exception {
                if (o.equals("出错")) {
                    return true;
                } else if (o.getClass()==GeRenRenWuModel.class) {
                   if(Boolean.parseBoolean(((GeRenRenWuModel)o).getIsdianping())){
                       return true;
                   }else {
                       return false;
                   }
                } else {
                    return true;
                }
            }
        }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer() {
                    @Override
                    public void accept(Object o) throws Exception {
                        if (o.equals("出错")) {
                            view.loadFaild();
                        } else if (o.equals("为空")) {

                        } else {
                            view.isShow(false);
                            view.showWenZiData((GeRenRenWuModel) o);
                        }
                    }
                });

filter的使用,筛选对应手机号所发布的任务的信息

 public static void getShaiXuanData(final String query) {
        final List list = new ArrayList<>();
        Observable.just("http://39.107.104.102:8080/wenzizhonghe.jsp").observeOn(Schedulers.newThread())
                .map(new Function() {
                    Map map = new ArrayMap();

                    @Override
                    public String apply(String s) throws Exception {
                        map.put("get", "quanti");
                        String response = HttpUtils.postResponse(s, map, "UTF-8");
                        return response;
                    }
                }).flatMap(new Function>() {
            @Override
            public ObservableSource apply(String s) throws Exception {
                Gson gson = new Gson();
                if (s.equals("sendText error!")) {
                    return Observable.just("出错");
                } else if (s.contains("shijian")) {
                    List list = gson.fromJson(s, new TypeToken>() {
                    }.getType());
                    return Observable.fromIterable(list);
                } else {
                    return Observable.just("为空");
                }
            }
        }).filter(new Predicate() {
            @Override
            public boolean test(Object o) throws Exception {
                if (((ShiXunItemData) o).getName().equals(query))
                    return true;
                else
                    return false;
            }
        }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer() {
                    @Override
                    public void accept(Object o) throws Exception {
                        ShiXunModel shiXunModel;
                        if (list.contains(((ShiXunItemData) o).getName())) {
                            shiXunModel = new ShiXunModel((ShiXunItemData) o);
                            view.showWenZiData(shiXunModel);
                        } else {
                            shiXunModel = new ShiXunModel(true, ((ShiXunItemData) o).getName(), false);
                            view.showWenZiData(shiXunModel);
                            shiXunModel = new ShiXunModel((ShiXunItemData) o);
                            view.showWenZiData(shiXunModel);
                            list.add(((ShiXunItemData) o).getName());
                        }
                    }
                });
    }

concatMap的用法,将多个Observable连接到一起进行发射,还是有顺序的连接

concatMap(new Function>() {
            @Override
            public ObservableSource apply(Object o) throws Exception {
                if (o.toString().equals("出错")) {
                    return Observable.just("出错");
                } else if (o.toString().equals("为空")) {
                    return Observable.just("为空");
                } else {
                    List lists = new ArrayList<>();
                    lists.add((CuoTiHuiZongModel) o);
                    return Observable.fromIterable(lists);
                }
            }
        })

21:在myeclipse中解决java.sql.SQLException: Before start of result set异常的方法
在执行完result = statement.executeQuery(sql);
记得加上result.next();

22:千万不要让androidmanifest.xml文件中有错误,如果有很明显的,系统直接提示的错误,但是你没有改正的话,那么如果你要在其他类中用到R类的话,那么R类就找不到了

23:一个图表库,地址为https://github.com/ggchxx/MPAndroidChart

24:一个recyclerview的适配器BaseRecyclerViewAdapterHelper,地址为https://github.com/CymChad/BaseRecyclerViewAdapterHelper
博客为https://www.jianshu.com/p/b343fcff51b0
要清空列表内容要用到replaceData方法,但是看源码如下

    public void replaceData(@NonNull Collection data) {
        // 不是同一个引用才清空列表
        if (data != mData) {
            mData.clear();
            mData.addAll(data);
        }
        notifyDataSetChanged();
    }

说明得重新创建一个引用才能清空列表,比如重新new, List list=new ArrayList();因为只要用了addData方法,数据就已经添加到原先的列表上了,所以只能重新new一个列表才能清空

以下还有一个可以随意拖动item,左滑右滑可以删除item的适配器,记得自己记录一下

public class CeShi extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    private List mData;
    private ItemDragAdapter mAdapter;
    private ItemTouchHelper mItemTouchHelper;
    private ItemDragAndSwipeCallback mItemDragAndSwipeCallback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ceshi);
        setTitle("ItemDrag  And Swipe");
        mRecyclerView = (RecyclerView) findViewById(R.id.rv_list);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mData = generateData(50);
        OnItemDragListener listener = new OnItemDragListener() {
            @Override
            public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos) {
                Log.d("d", "drag start");
                BaseViewHolder holder = ((BaseViewHolder) viewHolder);
//                holder.setTextColor(R.id.tv, Color.WHITE);
            }

            @Override
            public void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) {
                Log.d("d", "move from: " + source.getAdapterPosition() + " to: " + target.getAdapterPosition());
            }

            @Override
            public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) {
                Log.d("d", "drag end");
                BaseViewHolder holder = ((BaseViewHolder) viewHolder);
//                holder.setTextColor(R.id.tv, Color.BLACK);
            }
        };
        final Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setTextSize(20);
        paint.setColor(Color.BLACK);
        OnItemSwipeListener onItemSwipeListener = new OnItemSwipeListener() {
            @Override
            public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) {
                Log.d("d", "view swiped start: " + pos);
                BaseViewHolder holder = ((BaseViewHolder) viewHolder);
//                holder.setTextColor(R.id.tv, Color.WHITE);
            }

            @Override
            public void clearView(RecyclerView.ViewHolder viewHolder, int pos) {
                Log.d("d", "View reset: " + pos);//当item被左滑或者右滑消失之后,pos的值为-1
                BaseViewHolder holder = ((BaseViewHolder) viewHolder);
//                holder.setTextColor(R.id.tv, Color.BLACK);
            }

            @Override
            public void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos) {//该方法只有当item被滑动的从列表中消失之后,才会触发该方法
                Log.d("d", "View Swiped: " + pos);
            }

            @Override
            public void onItemSwipeMoving(Canvas canvas, RecyclerView.ViewHolder viewHolder, float dX, float dY, boolean isCurrentlyActive) {
                canvas.drawColor(ContextCompat.getColor(CeShi.this, R.color.gray));
//                canvas.drawText("Just some text", 0, 40, paint);
            }
        };

        mAdapter = new ItemDragAdapter(mData);
        mItemDragAndSwipeCallback = new ItemDragAndSwipeCallback(mAdapter);
        mItemTouchHelper = new ItemTouchHelper(mItemDragAndSwipeCallback);
        mItemTouchHelper.attachToRecyclerView(mRecyclerView);

        //mItemDragAndSwipeCallback.setDragMoveFlags(ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT | ItemTouchHelper.UP | ItemTouchHelper.DOWN);
        mItemDragAndSwipeCallback.setSwipeMoveFlags(ItemTouchHelper.START | ItemTouchHelper.END);//这个方法是设置item是从左滑还是从右滑,|是表示左滑或者右滑都可以,默认不设置是向右滑
        mAdapter.enableSwipeItem();
        mAdapter.setOnItemSwipeListener(onItemSwipeListener);//Swipe是设置item是否可以左右滑动
        mAdapter.enableDragItem(mItemTouchHelper);
        mAdapter.setOnItemDragListener(listener);//drag是设置item是否可以拖动变化位置
//        mRecyclerView.addItemDecoration(new GridItemDecoration(this ,R.drawable.list_divider));

        mRecyclerView.setAdapter(mAdapter);
//        mRecyclerView.addOnItemTouchListener(new OnItemClickListener() {
//            @Override
//            public void onSimpleItemClick(final BaseQuickAdapter adapter, final View view, final int position) {
//                ToastUtils.showShortToast("点击了" + position);
//            }
//        });
        mAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                CommonUtil.showToask(CeShi.this,"点击了"+position);
            }
        });
    }

    private List generateData(int size) {
        ArrayList data = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            data.add("item " + i);
        }
        return data;
    }
    public class ItemDragAdapter extends BaseItemDraggableAdapter {
        public ItemDragAdapter(List data) {
            super(R.layout.item_draggable_view, data);
        }

        @Override
        protected void convert(BaseViewHolder helper, String item) {
            switch (helper.getLayoutPosition() %
                    3) {
                case 0:
                    helper.setImageResource(R.id.iv_head, R.mipmap.ic_drawer_home);
                    break;
                case 1:
                    helper.setImageResource(R.id.iv_head, R.mipmap.ic_drawer_home);
                    break;
                case 2:
                    helper.setImageResource(R.id.iv_head, R.mipmap.ic_drawer_home);
                    break;
            }
            helper.setText(R.id.tv, item);
        }
    }

}

稍微总结一下,不管是swipe(左右滑)还是drag(上下拖动),ItemTouchHelper都是必须的,因为要用它来绑定recyclerview和适配器,做中间者,比如
itemTouchHelper=new ItemTouchHelper(new ItemDragAndSwipeCallback(shiPeiQi));
itemTouchHelper.attachToRecyclerView(recyclerView);

BaseSectionQuickAdapter适配器的使用

public class ShiXunYi extends ShiXunBaseFragment implements ShiXunYiContract.View {
    private SmartRefreshLayout smartRefreshLayout;
    private RecyclerView recyclerView;
    private ShiPeiQi shiPeiQi;
    private List list;

    @Override
    public int initUI() {
        return R.layout.shixunyi;
    }

    @Override
    public void initData(View view, @Nullable Bundle savedInstanceState) {
        smartRefreshLayout = (SmartRefreshLayout) view.findViewById(R.id.smart);
        recyclerView = (RecyclerView) view.findViewById(R.id.recycler);
        list = new ArrayList<>();
        ShiXunYiModel shiXunYiModel = new ShiXunYiModel(true, "第一个", true);
        ShiXunYiModel shiXunYiMode2 = new ShiXunYiModel(new ShiXunYiItemData("我是小标题"));
        ShiXunYiModel shiXunYiMode3 = new ShiXunYiModel(new ShiXunYiItemData("我是小标题"));
        ShiXunYiModel shiXunYiMode4 = new ShiXunYiModel(new ShiXunYiItemData("我是小标题"));
        ShiXunYiModel shiXunYiMode5 = new ShiXunYiModel(new ShiXunYiItemData("我是小标题"));
        ShiXunYiModel shiXunYiMode6 = new ShiXunYiModel(new ShiXunYiItemData("我是小标题"));
        ShiXunYiModel shiXunYiMode7 = new ShiXunYiModel(true, "第二个", false);
        ShiXunYiModel shiXunYiMode8 = new ShiXunYiModel(new ShiXunYiItemData("我是小标题"));
        ShiXunYiModel shiXunYiMode9 = new ShiXunYiModel(new ShiXunYiItemData("我是小标题"));
        list.add(shiXunYiModel);
        list.add(shiXunYiMode2);
        list.add(shiXunYiMode3);
        list.add(shiXunYiMode4);
        list.add(shiXunYiMode5);
        list.add(shiXunYiMode6);
        list.add(shiXunYiMode7);
        list.add(shiXunYiMode8);
        list.add(shiXunYiMode9);
        shiPeiQi = new ShiPeiQi(R.layout.body, R.layout.tou, list);
        GridLayoutManager gridLayoutManager=new GridLayoutManager(getContext(),2);
        recyclerView.setLayoutManager(gridLayoutManager);
        smartRefreshLayout.setOnRefreshListener(new OnRefreshListener() {
            @Override
            public void onRefresh(RefreshLayout refreshlayout) {
                refreshlayout.finishRefresh(800,true);
            }
        });
        smartRefreshLayout.setRefreshHeader(new ClassicsHeader(getContext()));
        recyclerView.setAdapter(shiPeiQi);
    }

    class ShiPeiQi extends BaseSectionQuickAdapter {

        public ShiPeiQi(int layoutResId, int sectionHeadResId, List data) {
            super(layoutResId, sectionHeadResId, data);
        }

        @Override
        protected void convert(BaseViewHolder helper, ShiXunYiModel item) {
            helper.setText(R.id.xiaotitle,(item.t).getXiaoTitle());
        }

        @Override
        protected void convertHead(BaseViewHolder helper, ShiXunYiModel item) {
            helper.setText(R.id.title,item.header);
            if(item.isMore())
                helper.setGone(R.id.more,false);
        }
    }
}

这个适配器的bean是有要求的,需要继承SectionEntity类,如下

public class ShiXunYiModel extends SectionEntity implements ShiXunYiContract.Model {
    private boolean isMore;

    public ShiXunYiModel(boolean isHeader, String header, boolean isMore) {
        super(isHeader, header);
        this.isMore = isMore;
    }

    public ShiXunYiModel(ShiXunYiItemData shiXunYiItemData) {
        super(shiXunYiItemData);
    }

    public boolean isMore() {
        return isMore;
    }

    public void setMore(boolean more) {
        isMore = more;
    }
}

public class ShiXunYiItemData {
    private String xiaoTitle;

    public ShiXunYiItemData(String xiaoTitle) {
        this.xiaoTitle = xiaoTitle;
    }

    public String getXiaoTitle() {
        return xiaoTitle;
    }

    public void setXiaoTitle(String xiaoTitle) {
        this.xiaoTitle = xiaoTitle;
    }
}

BaseMultiItemQuickAdapter适配器的使用:

public class ShiXunEr extends ShiXunBaseFragment implements ShiXunErContract.View {
    private SmartRefreshLayout smartRefreshLayout;
    private RecyclerView recyclerView;
    private ShiPeiQi shiPeiQi;
    private List list;

    @Override
    public int initUI() {
        return R.layout.shixuner;
    }

    @Override
    public void initData(View view, @Nullable Bundle savedInstanceState) {
        smartRefreshLayout = (SmartRefreshLayout) view.findViewById(R.id.smart);
        recyclerView = (RecyclerView) view.findViewById(R.id.recycler);
        list = new ArrayList<>();
        ShiXunErModel shiXunErModel = new ShiXunErModel(ShiXunErModel.IMG, 3);//这里的第二个参数是这个item所占的span的个数
        // 一个bean就对应着一个item,当紧挨的两个bean文件的span大于GridLayoutManager中的span时,就会将后一个bean放在下一行中,如果小于或者是等于的
        //话就会放在同一行
        ShiXunErModel shiXunErMode2 = new ShiXunErModel(ShiXunErModel.IMG_TEXT,4,"nihao a haha");
        ShiXunErModel shiXunErMode3 = new ShiXunErModel(ShiXunErModel.TEXT, 2);
        ShiXunErModel shiXunErMode4 = new ShiXunErModel(ShiXunErModel.IMG, 3);
        ShiXunErModel shiXunErMode5 = new ShiXunErModel(ShiXunErModel.IMG_TEXT,6,"你哈啊啊啊啊啊");
        list.add(shiXunErModel);
        list.add(shiXunErMode2);
        list.add(shiXunErMode3);
        list.add(shiXunErMode4);
        list.add(shiXunErMode5);
        shiPeiQi=new ShiPeiQi(list);
        GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 6);
        recyclerView.setLayoutManager(gridLayoutManager);
        smartRefreshLayout.setOnRefreshListener(new OnRefreshListener() {
            @Override
            public void onRefresh(RefreshLayout refreshlayout) {
                refreshlayout.finishRefresh(800,true);
            }
        });
        smartRefreshLayout.setRefreshHeader(new ClassicsHeader(getContext()));
        shiPeiQi.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() {
            @Override
            public int getSpanSize(GridLayoutManager gridLayoutManager, int position) {
                return list.get(position).getSpanSize();
            }
        });
        recyclerView.setAdapter(shiPeiQi);
    }

    class ShiPeiQi extends BaseMultiItemQuickAdapter {

        public ShiPeiQi(List data) {
            super(data);
            addItemType(ShiXunErModel.TEXT, R.layout.textitem);//addItemType方法使得bean的不同标识和布局对应起来
            addItemType(ShiXunErModel.IMG, R.layout.imageitem);
            addItemType(ShiXunErModel.IMG_TEXT, R.layout.text_imageitem);
        }

        @Override
        protected void convert(BaseViewHolder helper, ShiXunErModel item) {
            switch (helper.getItemViewType()) {//getItemViewType()方法是得到item的类型
                case ShiXunErModel.TEXT:
                    helper.setText(R.id.tv, item.getContent());
                    break;
                case ShiXunErModel.IMG_TEXT:
                    helper.setImageResource(R.id.iv, R.mipmap.ic_drawer_home)
                        .setText(R.id.tv,item.getContent());
                    break;
                case ShiXunErModel.IMG:
                    helper.setImageResource(R.id.iv, R.mipmap.logo_rmw);
            }
        }
    }
}
public class ShiXunErModel implements MultiItemEntity,ShiXunErContract.Model {
    public static final int TEXT = 1;
    public static final int IMG = 2;
    public static final int IMG_TEXT = 3;
    private int itemType;
    private int spanSize;
    private String content;

    public ShiXunErModel(int itemType, int spanSize, String content) {
        this.itemType = itemType;
        this.spanSize = spanSize;
        this.content = content;
    }

    public ShiXunErModel(int itemType, int spanSize) {
        this.itemType = itemType;
        this.spanSize = spanSize;
    }

    public int getSpanSize() {
        return spanSize;
    }

    public void setSpanSize(int spanSize) {
        this.spanSize = spanSize;
    }


    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public int getItemType() {
        return itemType;
    }
}

这种适配器不需要在new的时候传入视图,而是在定义的时候就给多个视图分好类别

25:SmartRefreshLayout刷新库,地址为https://github.com/scwang90/SmartRefreshLayout
添加如下依赖:compile 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.4-7'
注意了:这是开发过程中的一个坑,弄了好半天,SmartRefreshLayout中间的布局,如果不是recyclerview,NestedScrollView(即使有多个view,如textview,他俩也是可以显示的),那么就必须将其他视图,如textview,将他们放在一个relativelayout,linearlayout之类的,才能将textview之类的显示出来,不然是显示不出来的,比如

 

        

            

            
        
    

就以上那个布局,如果没有将TextView放在RelativeLayout中的话,在SmartRefreshLayout中是显示不出来的,只有RecyclerView可以显示出来,但是如果加上RelativeLayout,那么就能显示出来

26:在viewpager中如果添加的是fragment的话,就需要使用FragmentStatePagerAdapter设配器,不能再使用PagerAdapter了,设配器配置入下:

 public class FragmentAdapter extends FragmentStatePagerAdapter {
        private List fragments;

        public FragmentAdapter(FragmentManager fm, List fragments) {
            super(fm);
            this.fragments = fragments;
        }

        @Override
        public BaseFragment getItem(int position) {
            return fragments.get(position);
        }

        @Override
        public int getCount() {
            return fragments == null ? 0 : fragments.size();
        }

        public int getItemPosition(Object object) {
            return PagerAdapter.POSITION_NONE;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            //        super.destroyItem(container, position, object);
        }
    }

27:注意在mvp架构中,虽然在presenter文件中,持有对view的引用,但是如果在presenter文件中已经在子线程中,这是要操作view中的方法,虽然有view的引用,但是也不能直接使用,必须先切换回主线程才行,比如

...     
 }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer() {
            @Override
            public void accept(JiaoYuNewsModel jiaoYuNewsModel) throws Exception {
                view.showList(jiaoYuNewsModel);
            }
        });

如果不切换回主线程,那么会报错

28:jsoup框架,是java版的网络爬虫,记得学学,网址为http://www.open-open.com/jsoup/selector-syntax.htm
注意:


一个>表示下一个的意思,即div.thumb-img>a,表示class为thumb-img名的div的下一个a元素,div.thumb-img>a>img,表示class为thumb-img名的div的下一个a元素的下一个img元素,这是就代表img元素
又比如element.select("li>a[href]"),其中[]中间放的是属性,表示li标签的下一个含有href属性的a标签

29:在rxjava中,方法体内赋值的变量,在最后一个数据发射之后并且方法体结束后变量中的值将会全部释放,注意了,不能再在其他地方使用该变量了,所得的值为空,要在方法体内将所要的值传到相应的位置,比如

 public void jiaZaiViewPagerData() {
        modelList=new ArrayList<>();
        Observable.just("http://39.107.104.102:8080/gundongyemianwangzhi.jsp").observeOn(Schedulers.newThread())
                .map(new Function>() {
                    Gson gson=new Gson();
                    @Override
                    public List apply(String s) throws Exception {
                        modelList=gson.fromJson(ConvertUtils.inputStream2String(HttpUtil.getInputStreamFromUrl(s),"UTF-8"),new TypeToken>(){}.getType());
                        return modelList;
                    }
                }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer>() {
            @Override
            public void accept(List list) throws Exception {
                view.gunDongViewPager(list);//通过在view层创造方法来讲值传过去
            }
        });
    }

30:cardview的这四个属性全设置成8dp就好看,如下所示

    android:layout_margin="8dp"
    app:cardCornerRadius="8dp"
    app:cardElevation="8dp"
    app:contentPadding="8dp

31:relativelayout布局不需要在text窗口下通过属性设置,直接在design窗口下拖动到自己喜欢的位置就行,也是挺难拖得,有的还是得在design窗口下设置了

32:webview有时候加载出来的网页是电脑版的,有时候是手机版的,我那时候爬的是中国新闻网上的新闻的网址,然后拿webview加载出来是电脑版的,然后我就在手机上搜索中国新闻网,查看中国新闻网的手机版的网址,然后拿电脑打开手机版的网址,我发现手机版的网址就比电脑版的网址多了一个m,然后我在webview中多加一个m,结果加载出来的都是手机版的网页,哈哈,如果要是没有那个规律,直接爬取手机版的网页就得了,不过我没试过爬手机版的网页

33:又在自己的电脑中发现了一个工具文件夹,记得总结总结
E:\YiZhi\sdk\src\main\java\com\zyw\horrarndoo\sdk\utils

34:Glide就是比Picasso强,同样是流式三步曲,Glide在内部已经实现了子线程的切换,而Picasso需要自己创建子线程。

35:我用webview加载手机版的网页,但是出来的还是电脑版的网页(网址是手机版的网址),后来添加了新的代码,如下所示,就出来了手机版的网页,如果是加载电脑版的网页,即使加了下面的这些代码,出来的网页也还是电脑版的,如果想加载手机版的网页,那就到手机的浏览器找到一个手机版的网页,记下来网址就行

    webView = (WebView) findViewById(R.id.webview);
        WebSettings webSettings=webView.getSettings();
        webSettings.setUseWideViewPort(true);
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webSettings.setSupportMultipleWindows(true);
        webSettings.setLoadWithOverviewMode(true);
        webView.setWebChromeClient(new WebChromeClient());
        webView.requestFocus();
        webView.loadUrl(((LocalNewsModel)intent.getParcelableExtra("zhi")).getHref());

36:eventbus框架的使用:添加如下依赖:注意,eventbus发射的数据可以被多处地方接收
compile 'org.greenrobot:eventbus:3.1.1'
代码如下:

public class MessageEvent {(数据类型)
    private String messsage;

    public MessageEvent(String messsage) {
        this.messsage = messsage;
    }

    public String getMesssage() {
        return messsage;
    }

    public void setMesssage(String messsage) {
        this.messsage = messsage;
    }
}

在MainActivity.java文件中(发射数据)

 EventBus.getDefault().postSticky(new MessageEvent(intent.getStringExtra("biaoshi").split(",")[2]));

在LocalNews.java文件中(接收数据,多次接受,而不是就接收一次,每次进入该页面都会接收)

    @Subscribe(threadMode = ThreadMode.MAIN,sticky = true,priority = 1)//因为不是立马就处理消息,所以设置消息处理的优先级,priority的值越小,优先级越低
    public void sendMessage(MessageEvent messageEvent) {
        Log.i("chengshi", messageEvent.getMesssage());
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EventBus.getDefault().register(this);//在需要接受消息的文件中进行注册和反注册
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

参考文档在:http://blog.csdn.net/chen_lian_/article/details/51439119
关于ThreadMode
假如我们需要在不同的线程中接收消息,可以在注解中设置ThreadMode。
POSTING :默认的 ThreadMode,表示在执行 Post 操作的线程直接调用订阅者的事件响应方法,不论该线程是否为主线程(UI 线程)。
MAIN : 在主线程中执行响应方法。
BACKGROUND : 在后台线程中执行响应方法。
ASYNC : 不论发布线程是否为主线程,都使用一个空闲线程来处理。

37:记得看看yunzhijiaoyu项目中的一个类,叫CommonUtil类,不知道是从哪个项目中拿来的,忘了是电脑上的哪个项目了,记得找找,里面有很多功能

38: rxjava注意点,不能return null,会报错,rxjava中不可以传递null

Observable.just(woDeShouCangModel).observeOn(Schedulers.newThread())
                .map(new Function() {
                    @Override
                    public Integer apply(WoDeShouCangModel woDeShouCangModel) throws Exception {
                        DataSupport.deleteAll(WoDeShouCang.class,"href=?",woDeShouCangModel.getHref());
                        return 1;//不能返回null
                    }
                }).observeOn(AndroidSchedulers.mainThread())
                .subscribe();
    }

39:litepal数据库框架,不怎么好,不能设置主键,有默认主键,但只能是long类型,只能通过long类型的主键删除单个数据,记得学学dbflow框架,又发现一个缺点,就是列名不能包含大写字母,table名可以包含大写字母。

40:PreferencesUtils中保存的数据可以在多个页面共享使用,以前以为只能在同一个activity中保存和获取了,而且好像还可以跨进程获取,没试过,厉害了

41:还是用ActivityManagerUtil(这是一个工具类)来管理activity吧,方便管理

42:在网络框架这方面我有点弱了,记得好好看看retrofit和okhttp3

43:解决recyclerview与scrollview的滑动冲突的方法,博客在https://www.jianshu.com/p/30b5ca973cd2,用完之后,发现问题解决了,但是滑动起来可迟钝了,但是如果放在android.support.v4.widget.NestedScrollView这个view中的话,滑动起来就很灵活,代码如下:




    

        
    

    

        

            

                

                    

                    

                    

                    

                        
                    
                
            

        
    

    

另外点击floatactionbutton可以立马跳到最顶端,给NestedScrollView设置点击事件,注意不能是给ScrollView设置点击事件,不然是跳不到最顶端的,代码如下所示:

@Override
    public void onClick(View v) {
        nestedScrollView.post(new Runnable() {
            @Override
            public void run() {
                nestedScrollView.fullScroll(View.FOCUS_UP);
            }
        });
    }

44:如果你的很多layout文件中的同一类型view的id都一样,那么系统将会找不到你在java文件中所要找的真正的view的id,进而报空指针异常,你就按住ctrl+鼠标左键,如果出来的列表中有你所需要的那个layout文件,那么就能找到,否则就找不到

45:将textview中多余的文字用省略号代替

android:ellipsize="end"//省略号出现在末尾
android:maxLines="4"//最多行数是4行
android:maxWidth="200dp"//最多宽度是200dp

46:一个优雅的对话框库,依赖为compile 'cn.pedant.sweetalert:library:1.3'
网址为https://github.com/pedant/sweet-alert-dialog
这个有个不好的地方就是,一个SweetAlertDialog引用的堆地址只能用一次,就是当点击了对话框的确定按钮后,这个对话框的引用就要指向新的堆地址(就是new一个新的对象),否则屏幕将被上一个对话框占有,使得屏幕不能被点击。不过sweetAlertDialog还有个dismiss方法,使得sweetAlertDialog消失,应该也能重复使用同一个堆空间,没试了,只是自己猜测的。

47:有时候用代码改view的属性要比在xml中添加view的属性跟有用,因为即使在xml中添加了属性有时候也不会出现想要的效果,但是代码就出来效果了,而且还不用提升app.gradle中的minSdkVersion,比如

 
toolbar.setTitleTextColor(Color.WHITE);//但是用代码改变属性,都不用提升minSdkVersion就改好了

48:一个点击就弹出一个菜单的view库,以前使用过,但是没有记录,依赖为:compile 'io.github.yavski:fab-speed-dial:1.0.6',网址为:https://github.com/liang1075963999/fab-speed-dial-master,注意了,这个view设置单击事件后,不能被响应,不知道为啥,当时是设置menu为空,然后设置单击事件,发现没响应单击事件。注意要将这个视图要放在framelayout中,这样当它弹出菜单后,菜单不会将它上面的视图挤得看不见了,并且点击一下其他地方,菜单会自动收起来,如果不是framelayout的话,就收不起来。如下面这个布局:



    
    
    
    
    

49:也是一个点击就弹出一个菜单的view库,这个还可以改变方向,变为向左或者是向右,上面那个库不行,更灵活,依赖为:compile 'cc.trity.floatingactionbutton:library:1.0.0',部分代码如下:

    

            

            
        

50:修正一种错误的观点,示例代码如下

Food food=new Food();
Food food1=food;

此时food1指向的是food指向的堆地址,而不是food的栈地址,也就是说如果food为

Food food=null;
Food food1=food;
food=new Food();

此时food1指向的还是null,而food指向的却是新new出来的堆地址

51:一个item侧滑布局库,网址为https://github.com/mcxtzhang/SwipeDelMenuLayout,依赖为:compile 'com.github.mcxtzhang:SwipeDelMenuLayout:V1.3.0'

52:一个筛选的下拉框,还算能用,其他就不如这个了,其他太难,太复杂,依赖为compile 'com.github.dongjunkun:DropDownMenu:1.0.4',网址为https://github.com/dongjunkun/DropDownMenu

53:一个时间选择器,还有三级联动的选择器,这个库功能强大,网址为https://github.com/Bigkoo/Android-PickerView,依赖为compile 'com.contrarywind:Android-PickerView:3.2.7'

54:只要是涉及到网络或者是数据库的,直接就用mvp架构写就行,因为都耗时。

55:要根据自己的需求将HttpUtil中的关于网络的方法进行改进,改成自己所需要的,这个项目中我就改了不少,可以看看。

56:解决java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionVie...异常的方法,如下对话所示
我也报了同样的错,解决方法:集合数据一旦发生改变,立马得调用notifyDataSetChanged();,我就是因为再调用list.clear(),方法后没有及时调用 notifyDataSetChanged()方法,导致的,现在已经解决,希望能给犯同样错误的小伙伴带来帮助Re: jiong103 2017-12-21 18:17发表 [回复] 回复RxWorld:我去,还真的是这样子,我把 datalist 放在子线程进行计算修改,然后切换到 主线程去 notify,结果就异常。没有立马notify引出的异常。目前用楼主的 方法catch 住了。搞了我一条。。wuwuRe: RangeAlpha 2017-12-13 15:49发表 [回复] 回复RxWorld:真是十分感谢Re: woaihongxin 2017-09-23 21:02发表 [回复] [引用] [举报]果然如此,谢谢大神的指点!!!不过这样列表会闪屏怎么办呢。

57:intent可以在activity之间进行传值,当一个activity中放的是fragment时,这是如果想用activity传值给fragment的话,可以调用fragment中的getActivity().getIntent()来获取值。

58:上传的图片必须要压缩才行,不然太大了,每次下载都花很多流量,代码如下:

Bitmap bitmap=ImageUtils.compressByQuality(BitmapFactory.decodeFile(string),10);//string是图片所在的位置
String s = HttpUtils.sendCompressFile("http://39.107.104.102:8080/uploadtouxiang.jsp", ConvertUtils.bitmap2Bytes(bitmap, Bitmap.CompressFormat.JPEG), user + ".jpg");
...
public static String sendCompressFile(String urlPath, byte[]bytes, String newName) throws Exception {//发送压缩后的图片,一下子就变的非常小了,省流量
        String end = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";
        URL url = new URL(urlPath);
        HttpURLConnection con = (HttpURLConnection)url.openConnection();
        con.setDoInput(true);
        con.setDoOutput(true);
        con.setUseCaches(false);
        con.setRequestMethod("POST");
        con.setRequestProperty("Connection", "Keep-Alive");
        con.setRequestProperty("Charset", "UTF-8");
        con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
        DataOutputStream ds = new DataOutputStream(con.getOutputStream());
        ds.writeBytes(twoHyphens + boundary + end);
        ds.writeBytes("Content-Disposition: form-data; name=\"file1\";filename=\"" + newName + "\"" + end);
        ds.writeBytes(end);
        ds.write(bytes);
        ds.writeBytes(end);
        ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
        ds.flush();
        InputStream is = con.getInputStream();
        StringBuffer b = new StringBuffer();
        int ch;
        while((ch = is.read()) != -1) {
            b.append((char)ch);
        }
        ds.close();
        return b.toString();
    }
...

59:一个底部的编辑框,依赖为compile 'me.shaohui:bottomdialog:1.1.9',网址为:https://github.com/shaohui10086/BottomDialog

60:双击返回键退出的代码:

private long firstTime = 0;
...
 @Override
    public void onBackPressed() {
    //super.onBackPressed();不能将父类的onBackPressed()方法也写一遍,不然按一次直接就退出了
        long secondTime = System.currentTimeMillis();
        if (secondTime - firstTime > 2000) {
            Toast.makeText(MainActivity.this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
            firstTime = secondTime;
        } else {
            RenWuGuanLi.count=0;
            ActivityManagerUtil.getAppManager().finishAllActivity();//或者是将该句代码换成System.exit(0);也能退出
        }
    }
...

61:在relativelayout中假设view a的layout_toLeftOf属性的属性值中出现的id,必须放在view a的前面才行,比如

 
        

            

            
        
        
    

62:即使一个视图的visibility属性是gone,在使用了VISIBLE之后,那个视图也会显示出来

63:一个searchview库,依赖为compile 'com.miguelcatalan:materialsearchview:1.4.0',网址为https://github.com/MiguelCatalan/MaterialSearchView,还可以设置历史记录,挺好的

63:当一个activity的主题是Theme.AppCompat.Light.NoActionBar时,也就是说没有activonbar时,可以用toolbar来实现actionbar的效果,下面的代码是在toolbar中填充menu的代码:

...
private static int i=0;
...
setSupportActionBar(toolbar);
...
 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        Log.d("MainActivity", "onCreateOptionsMenu");
        getMenuInflater().inflate(R.menu.menu_main, menu);// toolbar.inflateMenu(R.menu.menu_main);和这句代码的效果是一样的,写一个即可,在R.menu.menu_main文件中的item中加入app:showAsAction="always"属性,那么这个item,就会一直出现在toolbar中,不会是竖立的三个小点
        MenuItem item = menu.findItem(R.id.action_search);
        if(i==1){
            item.setVisible(true);
        }else {
            item.setVisible(false);
        }
        invalidateOptionsMenu();//有这句代码的话,onCreateOptionsMenu这个方法将会不停的重复,不管这句代码放在onCreateOptionsMenu方法的哪个位置,都是不停的重复执行onCreateOptionsMenu方法,使得toolbar中的按钮点击不灵敏,但是可以变成灵敏的,代码在下方
        searchView.setMenuItem(item);
        return true;
    }
...

然后在相应要显示menu的fragment中将i赋值为1,不显示menu的fragment中将i赋值为0就行。
变灵敏的代码如下,在每次创建fragment时,调用一下invalidateOptionsMenu(),不会不停的重复了,也达到了所要的效果,那为什么不重复了呢,因为调用了invalidateOptionsMenu方法之后,系统将会重新调用一次onCreateOptionsMenu方法,使用最新的menu,而原先之所以不停的重复是因为原先invalidateOptionsMenu方法是在onCreateOptionsMenu方法中写得,意思就是自己内部不停的废掉旧menu,使用新menu,死循环。

 public void onTabSelected(int position) {
        fragmentTransaction = fragmentManager.beginTransaction();
        switch (position) {
            case 0:
                i = 0;
                toolbar.setTitle("导航菜单");
                toolbar.dismissPopupMenus();
                toolbar.hideOverflowMenu();
                invalidateOptionsMenu();
                searchView.setVisibility(View.GONE);
                hideFragments(fragmentTransaction);
                if (daoHang != null) {
                    fragmentTransaction.show(daoHang);
                } else {
                    daoHang = new DaoHang();
                    fragmentTransaction.add(R.id.framelayout, daoHang);
                }
                break;
            case 1:
                i = 1;
                toolbar.setTitle("综合实训");
                invalidateOptionsMenu();
                searchView.setVisibility(View.VISIBLE);
                hideFragments(fragmentTransaction);
                if (shiXun != null) {
                    fragmentTransaction.show(shiXun);
                } else {
                    shiXun = new ShiXun();
                    fragmentTransaction.add(R.id.framelayout, shiXun);
                }
                break;
            case 2:
                i = 0;
                if (intent.getStringExtra("biaoshi").split(",")[1].equals(String.valueOf(1))) {
                    toolbar.setTitle("任务管理");
                    invalidateOptionsMenu();
                    searchView.setVisibility(View.GONE);
                    hideFragments(fragmentTransaction);
                    if (renWuGuanLi != null) {
                        fragmentTransaction.show(renWuGuanLi);
                    } else {
                        renWuGuanLi = new RenWuGuanLi();
                        fragmentTransaction.add(R.id.framelayout, renWuGuanLi);
                    }
                    break;
                } else if (intent.getStringExtra("biaoshi").split(",")[1].equals(String.valueOf(2))) {
                    toolbar.setTitle("个人任务");
                    invalidateOptionsMenu();
                    searchView.setVisibility(View.GONE);
                    hideFragments(fragmentTransaction);
                    if (geRenRenWu != null) {
                        fragmentTransaction.show(geRenRenWu);
                    } else {
                        geRenRenWu = new GeRenRenWu();
                        fragmentTransaction.add(R.id.framelayout, geRenRenWu);
                    }
                    break;
                }

            case 3:
                i = 2;
                if (intent.getStringExtra("biaoshi").split(",")[1].equals(String.valueOf(1))) {
                    toolbar.setTitle("课程管理");
                    invalidateOptionsMenu();
                    searchView.setVisibility(View.GONE);
                    hideFragments(fragmentTransaction);
                    if (tWoDeKeCheng != null) {
                        fragmentTransaction.show(tWoDeKeCheng);
                    } else {
                        tWoDeKeCheng = new TWoDeKeCheng();
                        fragmentTransaction.add(R.id.framelayout, tWoDeKeCheng);
                    }
                    break;
                } else if (intent.getStringExtra("biaoshi").split(",")[1].equals(String.valueOf(2))) {
                    toolbar.setTitle("我的课程");
                    invalidateOptionsMenu();
                    searchView.setVisibility(View.GONE);
                    hideFragments(fragmentTransaction);
                    if (woDeKeCheng != null) {
                        fragmentTransaction.show(woDeKeCheng);
                    } else {
                        woDeKeCheng = new WoDeKeCheng();
                        fragmentTransaction.add(R.id.framelayout, woDeKeCheng);
                    }
                }

                break;
            case 4:
                i = 0;
                toolbar.setTitle("个人信息");
                invalidateOptionsMenu();
                searchView.setVisibility(View.GONE);
                hideFragments(fragmentTransaction);
                if (geRenXinXi != null) {
                    fragmentTransaction.show(geRenXinXi);
                } else {
                    geRenXinXi = new GeRenXinXi();
                    fragmentTransaction.add(R.id.framelayout, geRenXinXi);
                }
                break;
            default:
                break;
        }
        fragmentTransaction.commit();
        fragmentTransaction = null;
    }

64:android 弹出软键盘将底部视图顶起有关问题的解决方法

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);//解决软键盘弹出界面变型问题

这个代码得放在activity中才有效,不能放在fragment中,没效果
就这一句代码,当然很有其他方法,网址为http://blog.csdn.net/ithouse/article/details/69255670

65:list转string数组,代码如下:

List list = new ArrayList();    
list.add("a1");    
list.add("a2");    
String[] toBeStored = list.toArray(new String[list.size()]);    
for(String s : toBeStored) {    
     System.out.println(s);    
}    

66:一个功能强大的tablayout,都不需要设配器,以前就已经收藏了,但是都没用,现在用了,依赖为:compile 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar',网址为https://github.com/H07000223/FlycoTabLayout,有时候这个库的demo中的xml文件中的属性的命名空间是tl,这是我们要将tl换成app,这样才会有效果,不然是没效果的。
有个属性是app:tl_tab_space_equal="true",这个属性的作用就是当你的
tablayout不足以将底部全占满的时候,设置了这个属性后,会将不满的地方均匀占有

67:一个可以展开和闭合的布局库:网址为https://github.com/iammert/ExpandableLayout,它里面有的代码错的了,因此我修改后的代码如下所示:我在这里强调一下setRenderer这个方法必须在添加Section之前调用,不然是看不到view的,什么也看不到,弄了一晚上才发现,这两句代码的执行是有顺序的,真坑

public class KeChengZhiShiDian extends BaseFragment implements KeChengZhiShiDianContract.View {
    private ExpandableLayout sectionLinearLayout;
    private String[] parents = new String[]{"第一节",
            "第二节", "第三节",
            "第四节", "第五节",
            "第六节"};

    @Override
    public int initUI() {
        return R.layout.kechengzhishidian;
    }

    @Override
    public void initData(View view, @Nullable Bundle savedInstanceState) {
        sectionLinearLayout = (ExpandableLayout)view. findViewById(R.id.expand);
        sectionLinearLayout.setRenderer(new ExpandableLayout.Renderer() {
            @Override
            public void renderParent(View view, FruitCategory model, boolean isExpanded, int parentPosition) {
                ((TextView) view.findViewById(R.id.tvParent)).setText(model.name);
                view.findViewById(R.id.arrow).setBackgroundResource(R.drawable.arrow_left);
            }

            @Override
            public void renderChild(View view, Fruit model, int parentPosition, int childPosition) {
                ((TextView) view.findViewById(R.id.tvChild)).setText(model.name);
            }
        });
        sectionLinearLayout.addSection(getSection());
        sectionLinearLayout.addSection(getSection());
        sectionLinearLayout.addSection(getSection());
        sectionLinearLayout.addSection(getSection());
        sectionLinearLayout.addSection(getSection());
        sectionLinearLayout.setExpandListener(new ExpandCollapseListener.ExpandListener() {
            @Override
            public void onExpanded(int i, FruitCategory o, View view) {
                view.findViewById(R.id.arrow).setBackgroundResource(R.drawable.arrow_down);
            }
        });
        sectionLinearLayout.setCollapseListener(new ExpandCollapseListener.CollapseListener() {
            @Override
            public void onCollapsed(int i, FruitCategory fruitCategory, View view) {
                view.findViewById(R.id.arrow).setBackgroundResource(R.drawable.arrow_left);
            }
        });

    }

    public Section getSection() {
        Section section = new Section<>();
        FruitCategory fruitCategory = new FruitCategory(parents[(int) (Math.random() * parents.length)]);
        Fruit fruit1 = new Fruit("苹果");
        Fruit fruit2 = new Fruit("橘子");
        Fruit fruit3 = new Fruit("香蕉");
        Fruit fruit4 = new Fruit("葡萄");
        Fruit fruit5 = new Fruit("西瓜");
        Fruit fruit6 = new Fruit("鸭梨");
        section.parent = fruitCategory;
        section.children.add(fruit1);
        section.children.add(fruit2);
        section.children.add(fruit3);
        section.children.add(fruit4);
        section.children.add(fruit5);
        section.children.add(fruit6);
        section.expanded = false;
        return section;
    }
}

在Fruit.class文件中

public class Fruit {
    public String name;


    public Fruit(String name) {
        this.name = name;
    }
}

在FruitCategory.class文件中

public class FruitCategory {
    public String name;


    public FruitCategory(String name) {
        this.name = name;
    }
}

68:一个对话框库,其中已封装的对话框类型有,常规对话框、列表框、输入框、进度框,网址为:https://github.com/mylhyl/Android-CircleDialog,依赖为:compile 'com.mylhyl:circleDialog:2.2.1'

69:如果要在fragment中重写onActivityResult方法的话,切记要用fragment执行startActivityForResult方法,不能用activity执行startActivityForResult方法,否则是接收不到返回值的,记得在OpenFileUtil.java工具类中,原先的只有activity执行startActivityForResult方法,加入如下方法,就有了fragment的了:

    public void fragmentOpenFile(Fragment fragment, String leixing) {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType(leixing);
        intent.addCategory("android.intent.category.OPENABLE");
        fragment.startActivityForResult(intent, 1);
    }

然后在fragment中重写onActivityResult方法即可,如下

    @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode==1){
            imageView.setImageBitmap(ImageUtils.compressByQuality(ImageUtils.getBitmap(ConvertUtils.getFileAbsolutePath(getActivity(),data.getData())),15));
            path=ConvertUtils.getFileAbsolutePath(getActivity(),data.getData());
            gengxin.setVisibility(View.VISIBLE);
        }
    }

69:如果发生oom的话,可以在androidmanifest.xml文件中加入如下两句代码

android:hardwareAccelerated="true"
android:largeHeap="true"

70:关于图片压缩,以后就用比例压缩,不要再用质量压缩了,比例压缩不会失真,而质量压缩会失真的,而且质量压缩还很难用,因为图片的大小可能不同,这样一样的代码处理不同的图片,会出现不同的效果,而比例压缩就不会,具体代码如下:

ImageUtils.compressByScale(BitmapFactory.decodeFile(string), 400, 550);

71:关于路径的分割,具体参考网址:http://blog.csdn.net/zhuhai__yizhi/article/details/48158707
如果想以"."和""来分隔字符,就需要使用转移字符。

其中"."对应如下:

在java中函数split(".")必须是是split("\.")。

其中""对应如下:

在java中函数split("")必须是是split("\\")。

72:当你使用BaseRecyclerViewAdapterHelper这个库的时候,发现找不到对应的监听器的时候,可以通过helper.itemView来找到对应的view设置对应的监听器,如下所示

 public class ShiPeiQi extends BaseItemDraggableAdapter {
        public ShiPeiQi(@LayoutRes int layoutResId, @Nullable List data) {
            super(layoutResId, data);
        }

        @Override
        protected void convert(BaseViewHolder helper, final KeChengZhiShiDianModel item) {
            helper.setChecked(R.id.xuanzhe,false);
            ((EditText)helper.itemView.findViewById(R.id.bianji)).addTextChangedListener(new TextWatcher() {//addTextChangedListener这个方法就直接是找不到的,只能是在helper.itemView中自己定义
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    item.setBiaoti(s.toString());
                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            });
            ((CheckBox)helper.itemView.findViewById(R.id.xuanzhe)).setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {//setOnCheckedChangeListener这个方法也是直接找不到的
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    item.setParent(isChecked);
                }
            });
           /* helper.setText(R.id.bianji,item.getBiaoti())
                    .setChecked(R.id.xuanzhe,item.isParent());*/
        }
    }

73:BaseRecyclerViewAdapterHelper这个库中的OnItemDragListener和OnItemSwipeListener很牛逼,当你移动item,或者是滑出去item,对应的list中的数据就会移动到相应的位置或者是移除,牛逼,还有notifyDataSetChanged这个方法很厉害,只要一调用这个方法,就会将recyclerview的item进行重新布局,即重新调用适配器的convert方法。这个适配器中的item的布局用到都是同一个布局,并不是每创建一个item就去重新加载布局,当上一个改动了item之后(这里的改动是指使view消失或者出现之类的,本质上的改变),下一个item将会继续使用上一个item修改后的布局

74:字符串的substring()方法,是拿原字符串的一个副本进行的操作,原字符串还是原来的值,并没有发生改变。

75:textview的setText方法中的参数,不能是int类型,不然会报android.content.res.Resources$NotFoundException: String resource ID #0x1异常,那时候就这个弄了好久啊,真坑。

76:监听软键盘的收起和打开

public class SoftKeyBoardListener {
    private View rootView;  //activity的根视图
    int rootViewVisibleHeight;  //纪录根视图的显示高度
    private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener;
    public SoftKeyBoardListener(Activity activity) {
        //获取activity的根视图
        rootView = activity.getWindow().getDecorView();
        //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //获取当前根视图在屏幕上显示的大小
                Rect r = new Rect();
                rootView.getWindowVisibleDisplayFrame(r);
                int visibleHeight = r.height();
                System.out.println(""+visibleHeight);
                if (rootViewVisibleHeight == 0) {
                    rootViewVisibleHeight = visibleHeight;
                    return;
                }
                //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
                if (rootViewVisibleHeight == visibleHeight) {
                    return;
                }
                //根视图显示高度变小超过200,可以看作软键盘显示了
                if (rootViewVisibleHeight - visibleHeight > 200) {
                    if (onSoftKeyBoardChangeListener != null) {
                        onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight);
                    }
                    rootViewVisibleHeight = visibleHeight;
                    return;
                }
                //根视图显示高度变大超过200,可以看作软键盘隐藏了
                if (visibleHeight - rootViewVisibleHeight > 200) {
                    if (onSoftKeyBoardChangeListener != null) {
                        onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight);
                    }
                    rootViewVisibleHeight = visibleHeight;
                    return;
                }
            }
        });
    }
    private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
        this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener;
    }
    public interface OnSoftKeyBoardChangeListener {
        void keyBoardShow(int height);
        void keyBoardHide(int height);
    }
    public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
        SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity);
        softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener);
    }
}

在activity或者是fragment中写上如下代码即可

SoftKeyBoardListener.setListener(getActivity(), new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
            @Override
            public void keyBoardShow(int height) {
                Log.d("ShiXunZongJie", "出现了");
            }
            @Override
            public void keyBoardHide(int height) {
                Log.d("ShiXunZongJie", "隐藏了");
            }
        });

77:一个点击按钮就跳出菜单的库,依赖为:compile 'com.lzp.floatingactionbutton:floatingactionbuttonplus:1.0.0',网址为https://github.com/550609334/FloatingActionButtonPlus

78:我试了一堆的floatingactionbutton的自定义控件,但都或多或少有点毛病,最后发现我的手机是华为的,只要把华为的底部的虚拟工具栏隐藏之后,功能就全正常了,很奇怪。

79:设置RecycleView的item间距的方法,网址为:http://blog.csdn.net/csdndouniwan/article/details/51762269
代码为:

public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
    private int space;

    public SpacesItemDecoration(int space) {
        this.space = space;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view,
                               RecyclerView parent, RecyclerView.State state) {
        outRect.left = space;
        outRect.right = space;
        outRect.bottom = space;

        // Add top margin only for the first item to avoid double space between items
        if (parent.getChildPosition(view) == 0)
            outRect.top = space;
    }
}

...
recyclerView.addItemDecoration(new SpacesItemDecoration(80));
...

80:用gson转换json数据到列表的时候TypeToken中的范型必须是List<你的bean文件>,那时候只写了个bean文件,弄了好长时间,才发现那里出错了,正确的如下:

 List sShiXunJiHuaModelList = gson.fromJson(s, new TypeToken>(){}.getType());

81:一个工具库,网址为https://github.com/chaychan/BlogFileResource,其中包含打开手机文件的工具类

82:文件的上传和下载是最好是用service做,因为如果用线程做的话,当下载或者是上传完毕后,如果还是下载或者是上传的activity页面还好,如果下载或者是上传的activity页面已经销毁的话,这是如果还有toast之类的操作,会报空指针异常。

83:service当用startservice启动时,会调用service中的onStartCommand方法,如果是bindservice启动的话,调用的是onBind方法,可以在intent中携带数据,在onBind方法中的intent参数就可以接收到activity中放入的数据。

84:用service实现的上传功能,当上传完成后,并用BroadcastReceiver和activity进行通信,注意ServiceConnection,当时出错了,位置放错了,代码如下:

public class UploadService extends Service {
    private ArrayList arrayList;
    private Intent intent1=new Intent("dongtaiputong");

    @Override
    public IBinder onBind(Intent intent) {
        arrayList=intent.getStringArrayListExtra("zhi");
        upload(arrayList.get(0),arrayList.get(1),arrayList.get(2));
        return null;
    }
    private void upload(String path, final String user, final String time) {
        Observable.just(path).observeOn(Schedulers.newThread())
                .map(new Function() {
                    String s;

                    @Override
                    public Object apply(String string) throws Exception {
                        String[] strings = string.split("\\.");
                        Log.d("ShiXunJiHuaPresenter", "strings.length:" + strings.length);
                        switch (strings.length) {
                            case 2:
                                s = HttpUtils.sendAnyFile("http://39.107.104.102:8080/uploadkejian.jsp", FileUtils.readFile2Bytes(string), user + "_" + time +
                                        "_" + new SimpleDateFormat("MM-dd-HH:mm:ss").format(new Date(System.currentTimeMillis())) + "." + strings[1]);
                                break;
                            case 3:
                                s = HttpUtils.sendAnyFile("http://39.107.104.102:8080/uploadkejian.jsp", FileUtils.readFile2Bytes(string), user + "_" + time +
                                        "_" + new SimpleDateFormat("MM-dd-HH:mm:ss").format(new Date(System.currentTimeMillis())) + "." + strings[2]);
                                break;
                            case 4:
                                s = HttpUtils.sendAnyFile("http://39.107.104.102:8080/uploadkejian.jsp", FileUtils.readFile2Bytes(string), user + "_" + time +
                                        "_" + new SimpleDateFormat("MM-dd-HH:mm:ss").format(new Date(System.currentTimeMillis())) + "." + strings[3]);
                                break;
                            case 5:
                                s = HttpUtils.sendAnyFile("http://39.107.104.102:8080/uploadkejian.jsp", FileUtils.readFile2Bytes(string), user + "_" + time +
                                        "_" + new SimpleDateFormat("MM-dd-HH:mm:ss").format(new Date(System.currentTimeMillis())) + "." + strings[4]);
                                break;
                            case 6:
                                s = HttpUtils.sendAnyFile("http://39.107.104.102:8080/uploadkejian.jsp", FileUtils.readFile2Bytes(string), user + "_" + time +
                                        "_" + new SimpleDateFormat("MM-dd-HH:mm:ss").format(new Date(System.currentTimeMillis())) + "." + strings[5]);
                                break;
                            case 7:
                                s = HttpUtils.sendAnyFile("http://39.107.104.102:8080/uploadkejian.jsp", FileUtils.readFile2Bytes(string), user + "_" + time +
                                        "_" + new SimpleDateFormat("MM-dd-HH:mm:ss").format(new Date(System.currentTimeMillis())) + "." + strings[6]);
                                break;
                        }
                        return s;
                    }
                }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer() {
            @Override
            public void accept(Object o) throws Exception {
                if (o.equals("xinxi=chenggong")) {
                    CommonUtil.showToask(UploadService.this, "上传成功");
                    intent1.putExtra("tongzhi","chenggong");
                    sendBroadcast(intent1);
                    writeDataBase(new ShangChuanLiShi(arrayList.get(1), arrayList.get(2),
                            "上传路径为:"+arrayList.get(0), new SimpleDateFormat("MM-dd-HH:mm:ss").format(new Date(System.currentTimeMillis()))));
                } else {
                    intent1.putExtra("tongzhi","shibai");
                    sendBroadcast(intent1);
                    CommonUtil.showToask(UploadService.this, "上传失败");
                }
            }
        });
    }

    private void writeDataBase(ShangChuanLiShi shangChuanLiShi) {
        Observable.just(shangChuanLiShi).observeOn(Schedulers.newThread())
                .subscribe(new Consumer() {
                    @Override
                    public void accept(ShangChuanLiShi shangChuanLiShi) throws Exception {
                        shangChuanLiShi.save();
                    }
                });
    }
}

activity中的代码如下:

public class ShiXunJiHua extends BaseFragment implements ShiXunJiHuaContract.View, View.OnClickListener {
    private TextView shiPing;
    private TextView wenBen;
    private ShiXunJiHuaPresenter shiXunJiHuaPresenter;
    private TextView xianShi;
    private Button shangChuan;
    private Intent intent;
    private TWoDeKeChengModel tWoDeKeChengModel;
    private RecyclerView recyclerView;
    private ShiPeiQi shiPeiQi;
    private List shiXunJiHuaModelList;
    private ServiceConnection serviceConnection;
    private SmartRefreshLayout smartRefreshLayout;
    private SweetAlertDialog sweetAlertDialog;
    private MyBroadcast myBroadcast;

    @Override
    public int initUI() {
        return R.layout.shixunjihua;
    }

    @Override
    public void initData(View view, @Nullable Bundle savedInstanceState) {
        intent = getActivity().getIntent();
        tWoDeKeChengModel = intent.getParcelableExtra("zhi");
        shiXunJiHuaPresenter = new ShiXunJiHuaPresenter(this);
        wenBen = (TextView) view.findViewById(R.id.wenben);
        shiPing = (TextView) view.findViewById(R.id.shiping);
        xianShi = (TextView) view.findViewById(R.id.xianshi);
        shangChuan = (Button) view.findViewById(R.id.shangchuan);
        smartRefreshLayout = (SmartRefreshLayout) view.findViewById(R.id.smart);
        recyclerView = (RecyclerView) view.findViewById(R.id.recycler);
        smartRefreshLayout.setRefreshHeader(new ClassicsHeader(getContext()));
        smartRefreshLayout.setOnRefreshListener(new OnRefreshListener() {
            @Override
            public void onRefresh(RefreshLayout refreshlayout) {
                refreshlayout.finishRefresh(800, true);
                shiXunJiHuaModelList = new ArrayList<>();
                shiPeiQi.replaceData(shiXunJiHuaModelList);
                shiXunJiHuaPresenter.readDataBase(tWoDeKeChengModel.getTeacher(), tWoDeKeChengModel.getShijian());
            }
        });
        myBroadcast = new MyBroadcast();
        getActivity().registerReceiver(myBroadcast, new IntentFilter("dongtaiputong"));
        sweetAlertDialog = new SweetAlertDialog(getContext(), SweetAlertDialog.PROGRESS_TYPE);
        shiXunJiHuaModelList = new ArrayList<>();
        shiPeiQi = new ShiPeiQi(R.layout.shangchuanitem, shiXunJiHuaModelList);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setAdapter(shiPeiQi);
        wenBen.setOnClickListener(this);
        shiPing.setOnClickListener(this);
        shangChuan.setOnClickListener(this);
        shiXunJiHuaPresenter.readDataBase(tWoDeKeChengModel.getTeacher(), tWoDeKeChengModel.getShijian());
        serviceConnection = new ServiceConnection() {//ServiceConnection创建一个就行,如果创建多个ServiceConnection的话,会报错,放的位置很重要,放在oncreate方法中
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {

            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        };
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1) {
            try {
                Log.d("ShiXunJiHua", ConvertUtils.getFileAbsolutePath(getActivity(), data.getData()));
                xianShi.setText("上传路径为:" + ConvertUtils.getFileAbsolutePath(getActivity(), data.getData()));
                shangChuan.setVisibility(View.VISIBLE);
            } catch (Exception e) {

            }
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        shiXunJiHuaPresenter = null;
        getActivity().unregisterReceiver(myBroadcast);
        getActivity().unbindService(serviceConnection);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.wenben:
                Utils.fragmentOpenFile(this, "*/*");
                break;
            case R.id.shiping:
                Utils.fragmentOpenFile(this, "video/*");
                break;
            case R.id.shangchuan:
                sweetAlertDialog.setTitleText("上传中,请稍后");
                sweetAlertDialog.show();
                Log.d("ShiXunJiHua", xianShi.getText().toString().substring(6));
                Intent intent2 = new Intent(getContext(), UploadService.class);
                ArrayList arrayList = new ArrayList<>();
                arrayList.add(xianShi.getText().toString().substring(6));
                arrayList.add(tWoDeKeChengModel.getTeacher());
                arrayList.add(tWoDeKeChengModel.getShijian());
                intent2.putStringArrayListExtra("zhi", arrayList);
                getActivity().bindService(intent2, serviceConnection, Context.BIND_AUTO_CREATE);
                break;
        }
    }

    @Override
    public void uploadSuccess() {
        xianShi.setVisibility(View.GONE);
        shangChuan.setVisibility(View.GONE);
        sweetAlertDialog.dismiss();
        shiXunJiHuaModelList = new ArrayList<>();
        shiPeiQi.replaceData(shiXunJiHuaModelList);
        shiXunJiHuaPresenter.readDataBase(tWoDeKeChengModel.getTeacher(), tWoDeKeChengModel.getShijian());
    }

    @Override
    public void addData(ShiXunJiHuaModel shiXunJiHuaModel) {
        shiPeiQi.addData(0, shiXunJiHuaModel);
    }

    public class ShiPeiQi extends BaseQuickAdapter {
        public ShiPeiQi(@LayoutRes int layoutResId, @Nullable List data) {
            super(layoutResId, data);
        }

        @Override
        protected void convert(BaseViewHolder helper, ShiXunJiHuaModel item) {
            helper.setText(R.id.path, item.getPath())
                    .setText(R.id.time, item.getShangChuanTime());
        }
    }
    private void uploadFaild() {
        sweetAlertDialog.dismiss();
    }
    public class MyBroadcast extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getStringExtra("tongzhi").equals("chenggong")) {
                uploadSuccess();
            }else {
                uploadFaild();
            }
        }
    }
}

85:这样写即使kecheng的长度太长,也不会将fenshu给覆盖住,因为是先申明的fenshu,然后才是kecheng在fenshu的左边


  
    
    

以下这种写法kecheng如果太长,就会将fenshu覆盖住,因为是先申明的kecheng,这时kecheng已经将宽全部覆盖了,然后fenshu又申明在kecheng的左边,所以就被覆盖了


    
    

以下还有一个布局,是自己写的,用到了RelativeLayout,可以看看,总结总结




    

        

            
            
        
    
        

            

            

            
        

    

86:注意了当涉及从一个数据库的表到另外一个表的查询的时候,要用多表查询,速度很快,不要用一个表一个表的查询,好傻逼啊,哈哈。

87:可以通过设置drawerlayout的setDrawerLockMode方法来关闭抽屉布局,如下:
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);

88:调用ConvertUtils这个工具类的时候要注意了,当调用ConvertUtils.inputStream2String(inputStream,"UTF-8")之后,此时流已经变成了字符串,流已经没有了,而不是将流的副本变成了字符串,再调用ConvertUtils.inputStream2Bytes(inputStream)将会出现空指针异常,因为流已经变成字符串了,已经没有流了,所以报空指针异常。

39:介绍一个插件:DatabindingConvert
一个简单的Android Studio 插件,把普通的布局文件转化成Databinding的布局

40:一个根据代码自动生成UML的插件

网址为:https://github.com/Jerey-Jobs/SimpleUML

另外一个项目中的东西,还未记录
1:一个ui库,注意把项目的 theme 的 parent 指向 QMUI.Compat 或 QMUI,至此,QMUI 可以正常工作。
依赖如下
compile 'com.qmuiteam:qmui:1.0.6'
github地址为https://github.com/QMUI/QMUI_Android

2:记得研究一下targetsdkversion

3:这个工具记录一下

package com.wenxi.biandianzhan.utils;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CommonUtil {

    public static boolean checkNetState(Context context){
        boolean netstate = false;
        ConnectivityManager connectivity = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if(connectivity != null)
        {
            @SuppressWarnings("deprecation")
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null) {
                for (int i = 0; i < info.length; i++)
                {
                    if (info[i].getState() == NetworkInfo.State.CONNECTED)
                    {
                        netstate = true;
                        break;
                    }
                }
            }
        }
        return netstate;
    }


    private static Toast mToast = null;
    public static void showToask(Context context, String text)
    {
        if (mToast == null) {
            mToast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
        } else {
            mToast.setText(text);
//            mToast.setDuration(duration);
        }
        mToast.show();
//        Toast.makeText(context, tip, Toast.LENGTH_SHORT).show();
    }

    public static void showToask(Context context, String text,int duration)
    {
        if (mToast == null) {
            mToast = Toast.makeText(context, text, duration);
        } else {
            mToast.setText(text);
            mToast.setDuration(duration);
        }

        mToast.show();
    }


    public static int getScreenWidth(Context context) {
        WindowManager manager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        Display display = manager.getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics();
        display.getMetrics(outMetrics);
        return outMetrics.widthPixels;
        //return display.getWidth();
    }

    public static int getScreenHeight(Context context) {
        WindowManager manager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        Display display = manager.getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics();
        display.getMetrics(outMetrics);
        return outMetrics.heightPixels;
        //return display.getHeight();
    }

    //dip转像素值
    public static int dip2px(Context context, double d) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (d * scale + 0.5f);
    }

    //像素值转dip
    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * 是否是手机号
     */
    public static boolean isMobileNumber(String mobile) {
        if (mobile.length() != 11) return false;
        // "^((\\d{7,8})|(0\\d{2,3}-\\d{7,8})|(1[34578]\\d{9}))$"
        Pattern p = Pattern.compile("^((1[3|5|8][0-9])|(14[5|7])|(17[0|1|6|7|8]))\\d{8}$");
        Matcher m = p.matcher(mobile);
        return m.matches();
    }

    /**
     * 是否是固话
     */
    public static boolean isTel(String tel) {
        Pattern p = Pattern.compile("^((\\d{7,8})|(0\\d{2,3}-\\d{7,8})|(1[34578]\\d{9}))$");
        Matcher m = p.matcher(tel);
        return m.matches();
    }

    /**
     * 是否是邮箱
     */
    public static boolean isEmail(String strEmail) {
        // String strPattern =
        // "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
        String strPattern = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";

        Pattern p = Pattern.compile(strPattern);
        Matcher m = p.matcher(strEmail);
        return m.matches();
    }

    /**
     * 是否是网址
     */
    public static boolean isWeb(String strWeb) {
        String strPattern = "(http://|ftp://|https://|www){0,1}[^\u4e00-\u9fa5\\s]*?\\.(com|net|cn|me|tw|fr)[^\u4e00-\u9fa5\\s]*";

        Pattern p = Pattern.compile(strPattern);
        Matcher m = p.matcher(strWeb);
        return m.matches();
    }

    /**
     * 功能:身份证的有效验证
     *
     * @param IDStr
     *            身份证号
     * @return 有效:返回"" 无效:返回String信息
     * @throws ParseException
     */
    public static boolean IDCardValidate(String IDStr) throws ParseException {
        @SuppressWarnings("unused")
        String errorInfo = "";// 记录错误信息
        String[] ValCodeArr = { "1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2" };
        String[] Wi = { "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7",
                "9", "10", "5", "8", "4", "2" };
        String Ai = "";
        // ================ 号码的长度 15位或18位 ================
        if (IDStr.length() != 15 && IDStr.length() != 18) {
            errorInfo = "身份证号码长度应该为15位或18位";
            return false;
        }
        // ================ 数字 除最后一位都为数字 ================
        if (IDStr.length() == 18) Ai = IDStr.substring(0, 17);
        else if (IDStr.length() == 15)
            Ai = IDStr.substring(0, 6) + "19" + IDStr.substring(6, 15);
        if (!isNumeric(Ai)) {
            errorInfo = "身份证15位号码都应为数字 ; 18位号码除最后一位外,都应为数字";
            return false;
        }
        // ================ 出生年月是否有效 ================
        String strYear = Ai.substring(6, 10);// 年份
        String strMonth = Ai.substring(10, 12);// 月份
        String strDay = Ai.substring(12, 14);// 月份
        if (!isDataFormat(strYear + "-" + strMonth + "-" + strDay)) {
            errorInfo = "身份证生日无效";
            return false;
        }
        GregorianCalendar gc = new GregorianCalendar();
        SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
        try {
            if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150
                    || (gc.getTime().getTime() - s.parse(
                    strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) {
                errorInfo = "身份证生日不在有效范围";
                return false;
            }
        } catch (NumberFormatException | ParseException e) {
            e.printStackTrace();
        }
        if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {
            errorInfo = "身份证月份无效";
            return false;
        }
        if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {
            errorInfo = "身份证日期无效";
            return false;
        }
        // ================ 地区码时候有效 ================
        @SuppressWarnings("rawtypes")
        Hashtable h = GetAreaCode();
        if (h.get(Ai.substring(0, 2)) == null) {
            errorInfo = "身份证地区编码错误";
            return false;
        }
        // ================ 判断最后一位的值 ================
        int TotalmulAiWi = 0;
        for (int i = 0; i < 17; i++) {
            TotalmulAiWi = TotalmulAiWi
                    + Integer.parseInt(String.valueOf(Ai.charAt(i)))
                    * Integer.parseInt(Wi[i]);
        }
        int modValue = TotalmulAiWi % 11;
        String strVerifyCode = ValCodeArr[modValue];
        Ai = Ai + strVerifyCode;

        if (IDStr.length() == 18) {
            if (!Ai.equals(IDStr)) {
                errorInfo = "身份证无效,不是合法的身份证号码";
                return false;
            }
        } else return true;
        return true;
    }

    /**
     * 功能:设置地区编码
     *
     * @return Hashtable 对象
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private static Hashtable GetAreaCode() {
        Hashtable hashtable = new Hashtable();
        hashtable.put("11", "北京");
        hashtable.put("12", "天津");
        hashtable.put("13", "河北");
        hashtable.put("14", "山西");
        hashtable.put("15", "内蒙古");
        hashtable.put("21", "辽宁");
        hashtable.put("22", "吉林");
        hashtable.put("23", "黑龙江");
        hashtable.put("31", "上海");
        hashtable.put("32", "江苏");
        hashtable.put("33", "浙江");
        hashtable.put("34", "安徽");
        hashtable.put("35", "福建");
        hashtable.put("36", "江西");
        hashtable.put("37", "山东");
        hashtable.put("41", "河南");
        hashtable.put("42", "湖北");
        hashtable.put("43", "湖南");
        hashtable.put("44", "广东");
        hashtable.put("45", "广西");
        hashtable.put("46", "海南");
        hashtable.put("50", "重庆");
        hashtable.put("51", "四川");
        hashtable.put("52", "贵州");
        hashtable.put("53", "云南");
        hashtable.put("54", "西藏");
        hashtable.put("61", "陕西");
        hashtable.put("62", "甘肃");
        hashtable.put("63", "青海");
        hashtable.put("64", "宁夏");
        hashtable.put("65", "新疆");
        hashtable.put("71", "台湾");
        hashtable.put("81", "香港");
        hashtable.put("82", "澳门");
        hashtable.put("91", "国外");
        return hashtable;
    }

    /**
     * 功能:判断字符串是否为数字
     *
     * @param str 字符串
     * @return 布尔值
     */
    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        return isNum.matches();
    }

    /**
     * 验证日期字符串
     *
     * @param str 日期
     */
    public static boolean isDataFormat(String str) {
        boolean flag = false;
        //String regxStr="[1-9][0-9]{3}-[0-1][0-2]-((0[1-9])|([12][0-9])|(3[01]))";
        String regxStr = "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$";
        Pattern pattern1 = Pattern.compile(regxStr);
        Matcher isNo = pattern1.matcher(str);
        if (isNo.matches()) flag = true;
        return flag;
    }




    /**
     * 设置状态栏字体图标为深色,需要MIUIV6以上
     * @param window 需要设置的窗口
     * @param dark 是否把状态栏字体及图标颜色设置为深色
     * @return  boolean 成功执行返回true
     *
     */
    public static boolean MIUISetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            Class clazz = window.getClass();
            try {
                int darkModeFlag = 0;
                Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                if(dark){
                    extraFlagField.invoke(window,darkModeFlag,darkModeFlag);//状态栏透明且黑色字体
                }else{
                    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
                }
                result=true;
            }catch (Exception e){

            }
        }
        return result;
    }



    /**
     * 设置状态栏图标为深色和魅族特定的文字风格,Flyme4.0以上
     * 可以用来判断是否为Flyme用户
     * @param window 需要设置的窗口
     * @param dark 是否把状态栏字体及图标颜色设置为深色
     * @return  boolean 成功执行返回true
     *
     */
    public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            try {
                WindowManager.LayoutParams lp = window.getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class
                        .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class
                        .getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                result = true;
            } catch (Exception e) {

            }
        }
        return result;
    }
}

4:https://github.com/QMUI/QMUI_Android和https://github.com/tyzlmjj/PagerBottomTabStrip中的xml文件中的内容,值得好好学习。

5:https://github.com/tyzlmjj/PagerBottomTabStrip底部导航库,扩展性很高,底部可以出现中间突出的按钮

6:https://github.com/youth5201314/banner,这个滚动栏库很好用,简单示例如下

   public void initData() {
        list=new ArrayList<>();
        list.add("https://camo.githubusercontent.com/44eeb7b3a25f1d34aa6d2ff7dd62c8f07af3b560/687474703a2f2f6f63656835316b6b752e626b742e636c6f7564646e2e636f6d2f62616e6e65725f6578616d706c65342e706e67");
        list.add("https://camo.githubusercontent.com/a8a5a87e676880aa64626cbea3fba78853f1be31/687474703a2f2f6f63656835316b6b752e626b742e636c6f7564646e2e636f6d2f62616e6e65725f6578616d706c65352e706e67");
        list.add("https://camo.githubusercontent.com/fa591b0ea9768e3722fcd690cc97f987867573d9/687474703a2f2f6f63656835316b6b752e626b742e636c6f7564646e2e636f6d2f62616e6e65725f6578616d706c65332e706e67");
        stringList=new ArrayList<>();
        stringList.add("第一");
        stringList.add("第二");
        stringList.add("第三");
        myImageLoader=new MyImageLoader();
        banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE);
        banner.setBannerTitles(stringList);
        banner.setDelayTime(2000);
        banner.setIndicatorGravity(BannerConfig.RIGHT);
        banner.setBannerAnimation(Transformer.Default);
        banner.setImages(list).setImageLoader(myImageLoader);
        banner.start();//没有这句话banner是显示不出的
    }

    @Override
    public void onStart() {
        super.onStart();
        banner.startAutoPlay();
    }

    @Override
    public void onStop() {
        super.onStop();
        banner.stopAutoPlay();
    }

7:解决listview,gridview在scrollview中的滑动冲突的问题,博客为:https://blog.csdn.net/qq_24531461/article/details/52634022?locationNum=12

public class MyGridView extends GridView {
    public MyGridView(Context context) {
        super(context);
    }

    public MyGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}

8:一个下拉筛选的库,dropdownmenu,地址https://github.com/dongjunkun/DropDownMenu

9:一个强大的webview库,https://github.com/Justson/AgentWeb,支持下载文件,观看视频,支付,跳转到应用等功能。

10:给TextView添加下划线的方法:
textView.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);

11:不想让系统的BottomNavigationView每次点击都有扩散的动画效果,那么就在xml代码中加入该句代码app:itemBackground="@null",并且系统的BottomNavigationView你只需要有灰色的图片即可,当你点击item的时候,系统会自动给item中的图片变色,变为app的主色调。

12:不让EditText一进入activity就获得焦点的方法:在EditText的父视图中加入这两行代码即可

android:focusable="true"
android:focusableInTouchMode="true"

13:Android获取res目录下图片的uri的方式:

//比如获取mipmap下的一张luo.png图片的uri
Uri.parse("android.resource://" + getApplicationContext().getPackageName() + "/" +R.mipmap.luo)

你可能感兴趣的:(开发项目中学到的东西)