android新手开发备忘录

1.使用 Integer.parseInt(string)将字符串转成int类型时的时候里面的字符串要去空格,只能去首尾的空格,否则会报java.lang.NumberFormatException。

2.valueof也可以把字符串转成int类型

3.try-catch是最好的解决bug的方式,与其等观察后台可能出现的数据错误不如先为可能的错误做好准备,数据可能不对,但是app不能崩溃。

4.少用对话框,对话框貌似无论如何都无法完全全屏,哪怕测量屏幕的高度赋给它。

5.将进度条放进对话框内以达到黑色覆盖的效果不是很好,因为对话框会与屏幕上部分有间隙。设置一个view覆盖全屏颜色为灰色再放置一个进度条是比较好的方法,若出现覆盖层不能拦截点击事件(覆盖层背后的控件响应点击事件了),可以设置覆盖层的clickable熟悉为true,fragment覆盖activity时点击事件错乱也可以这样做。

5.手动解析json时用opt比用get解析好,因为opt哪怕出错不会导致app崩溃。

6.当使用字节流读取文本时出现部分文字乱码,可以换成字符流readline。

7.若需要获取时间,尽量获取本地时间,system.getcurrenttimemillis(),因为网络时间不一定获取成功,也不一定获取的总是正确的,下面的代码可以获取网络时间。

new Thread(new Runnable() {
            @Override
            public void run() {
                URL urlTime = null;//取得资源对象
                try {
                    urlTime = new URL("http://www.baidu.com");
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
                URLConnection uc = null;//生成连接对象
                try {
                    uc = urlTime.openConnection();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    uc.connect(); //发出连接
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //取得网站日期时间
                ld = uc.getDate();
//                 转换为标准时间对象
                date = new Date(ld);

            }
        }).start();
        return date ;


8.webview各种回调方法执行时机和顺序绝不是你想的那样。
9.开发时任何从接口或网络返回的数据都要考虑是否为空,是否正确,是否不存在。
10.偶尔listview设置footview会与最后一个item间隔一个item距离,我也不知道为什么如下图所示最后一个”退出登录“就是footview。

11.如果listview或recycleview之类的控件中某些数据需要隐藏在一开始就不放进去是最好的选择, listview的convertView.setVisibility(View.INVISIBLE)会让item内容不显示但是仍有一个空位,若listview的 android:divider="@null",android:dividerHeight="1dp"则会发现形成了类似于分组的效果,像上面那张图片最上面的空行其实另一种item但是
不显示内容。若listview的convertview设置为gone则会彻底移除不占位置。gridview 无论将convertview设置为GONE或INVISIBLE都不会完全移除,都会留下一个空位,后面的item不会自己补上,有人说将item隐藏时同时将item的宽和高设置为0我没试过不知道会不会影响点击事件和复用。
12.隐藏掉listview或gridview的分割线然后给item和背景设置不同的颜色来形成分割线的效果要好得多。
13.貌似在sdk的一定版本以上时拨打用户的电话需要在代码里确认权限(即使清单文件里已经有权限了),代码如下:
 public boolean check() {
                PackageManager pm = getPackageManager();
                boolean permission = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.CALL_PHONE", "com.objectretail.bcc"));
                return permission;
            }
if(permission)为true则startActivity(intent)拨打电话,如果不判断编译会不通过。

14.webview使用时注意以下代码:       
 WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
	/*************************************/	
        /settings.setDomStorageEnabled(true);  /
        /settings.setGeolocationEnabled(true); /
	/这2行代码表示开启webview的localstorage,不过貌似要加上SD卡读取权限,我也不知道localstorage是什么/
	/**************************************/
        settings.setDefaultTextEncodingName("UTF-8");

15.webview的setchromeclient和setwebviewclient可以同时使用且两者回调方法不同可以实现不同的功能。

16.webview上传图片的事真烦,后面博客再写吧。

17.listview和gridview相互嵌套或在scrollview中的新的写法,重写onMeasure()方法:
@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }

18.下拉框的效果尽量别用下拉框来实现了,太丑了。
19.picasso和fresco的默认加载错误图片会在加载的url为空或不正确时出现,最重要的事情是app不会崩溃。
20.直接用多种布局的listview即可实现类似于微信分组显示的效果。
21.当textview中的文本因为背景图片的颜色改变而变得不那么显眼时,可以考虑将textview放入线性等其他布局中,给该布局设置一个任意背景色,再将textview的文本设置为与背景色反差较大的颜色就可以了。

22.判断listview的数据是否多于一屏,用于一些奇葩需求,比如当数据不足一屏时隐藏scrollbar,超过一屏时始终显示,代码如下(这段代码网上找到因为最后没用上这个需求):

scrollbar,listView.setOnScrollListener(new OnScrollListener() {  
              
            @Override  
            public void onScrollStateChanged(AbsListView view, int scrollState) {  
                // TODO Auto-generated method stub  
                  
            }  
              
            @Override  
            public void onScroll(AbsListView view, int firstVisibleItem,  
                    int visibleItemCount, int totalItemCount) {  
                // TODO Auto-generated method stub  
                  
                //有更多  
                if(totalItemCount > visibleItemCount){  
                  
                //不满一屏  
                }else{  
                      
                }  
            }  
        })  


23.让listview的scrollbar始终显示(即不触摸屏幕也显示)可这样设置:  

        android:fadeScrollbars="false"
        android:scrollbarFadeDuration="0"


24.让listview的scrollbar不显示布局里这样写:android:scrollbars="none" ,代码里可以这样写:

View.setVericalScrollbarEnabled(boolean) //false隐藏竖直的进度条
View.setHorizontalScrollBarEnabled(boolean)//false隐藏横着的进度条


25.应用的版本号可以在gradle文件或者清单文件配置,但是某些集成的第三方sdk只能读取清单文件的比如坑爹的百度自动更新。versionCode是给设备程序识别版本(升级)用的,必须是一个interger值,整数,代表app更新过多少次,versionName是给用户看的,可以写1.1 , 1.2等等版本,通常上传到应用市场的app版本号只能越来越高,同一个市场可以传同版本或高版本不能传低版本。

26.关于清单文件中的信息获取包括版本号思路如下(网上找到):在Android中,应用程序的版本号是在AndroidManifest.xml文件中进行配置的,而PackageInfo类则封装了从该配置文件中获取的所有信息,描述了包内容的整体信息,因此,可以使用PackageInfo对象的versionName属性获取应用的版本号。
要怎么获取PackageInfo对象呢?可以通过PackageManager对象来获取。PackageManager是一个检索当前已安装在设备上的相关应用程序包的各种信息的类。PackageManager对象中的getPackageInfo方法可以获取PackageInfo对象,该方法需要传递两个参数:应用包名和条件。通常情况下,应用程序的包名可以通过Activity或Context(Activity继承自Context)的getPackageName()方法获取,而添加可以有很多设置,通常设置为0。
最后是PackageManager对象的获取,Context对象提供了getPackageManager()方法来获取该对象。代码如下: 

   PackageManager manager = context.getPackageManager();
     PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
      String version = info.versionName;


27.Imageview的scaletype中的fitxy可以让图片自由伸展铺满整个imageview,显示验证码图片时必用。

28.使用webview加载页面失败时重写onReceivedError()方法可以修改失败的页面(加载另一个html,或让一个全屏的不透明页面覆盖整个webview),以及点击重新加载的逻辑,重新加载后(可能)会回调onPageFinished()方法,此时让该方法中的super.onPageFinished(view, url)最先执行,再执行隐藏自定义失败界面和进度条的代码可以避免因为隐藏过快导致又显示加载失败的系统默认页面。

29.使用viewpage时,viewPager.setOffscreenPageLimit(N);// 设置缓存页面,当前页面的相邻N各页面都会被缓存,之前以为设置为2就是左右各一页,其实是左右各两页。

30.onActivityResult的方法执行是在使用了startactivityforresult()跳转结束回到初始activity时才会回调,以别的方式进入要跳转的activity再回到初始activity时不会回调。

31. onActivityResult()方法被回调还有一个前提是之前的activity必须要用activity.this.finish()这个方法结束,之前没注意这个问题,一直只知道按后退键也会回调,其实是按后退键会在ondestroy()方法里调用finish()方法。setResult()是用来设置回调时要传递的参数的,要在finish()之前调用但使用时机还是比较麻烦。


32.关于setResult()的使用和当设置activity的启动模式为singletask时无法回调onActivityResult()的问题(我自己的项目中activity也是设置成singletask但是一直都可以回调,我也不知道这是为什么),看下面2个链接: onActivityResult()setResult()的调用时机:http://blog.csdn.net/liu_qiqi/article/details/38304033;singleInstance或singleTask的设置导致onActivityResult回调失效:http://blog.csdn.net/u013499299/article/details/50424032。


33.关于静态注册的广播和不绑定的service,他们一直运行在后台,即使在app已经关闭且进程被回收后还能保持运行(需要指定广播和服务运行在新的进程:android:process=“:xxxx”,要加冒号),如果app在运行时,这两者都能访问app中写的类,对象和方法,也能访问各种资源目录下的资源,但是当app被关闭,关于app所有的资源都被回收时,广播和服务应该就不能访问这些资源和方法了,这时候会发生什么我也不知道,我的做法是尽量避免在广播和服务里访问app的需要被动态分配的资源,只访问存储在本地的文件,保持低耦合。关于这一点我也不确定这么做对不对。


34.application的代码到底会被执行几次?app第一次运行时才会执行,还是每一次系统创建app的进程时才会被执行?


35.AlarmManager是闹钟服务,可以设定定时执行,是一个系统级的服务,运行一次就会一直存在(也会被系统回收);其写法和NotificationManager极其类似,可以设置定时启动服务或发送广播。


36.pendingIntent相当于是Intent的封装。通过pendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)系列方法从系统取得一个用于启动一个Activity的PendingIntent对象,可以通过pendingIntent.getService(Context context, int requestCode, Intent intent, int flags)方法从系统取得一个用于启动一个Service的PendingIntent对象可以通过pendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags)方法从系统取得一个用于向BroadcastReceiver的发送广播的PendingIntent对象.


37. Intent和PendingIntent的区别
a. Intent是立即使用的,而PendingIntent可以等到事件发生后触发,PendingIntent可以cancel
b. Intent在程序结束后即终止,而PendingIntent在程序结束后依然有效
c. PendingIntent自带Context,而Intent需要在某个Context内运行
d. Intent在原task中运行,PendingIntent在新的task中运行


38.静态注册的Brodcastreceiver和非绑定的service中的context可能要context.getApplicationContext才有用。

39.MD5可以用来比较两个字符串是否一样,字符串也可以直接用equals()来比较,下面贴一个生成字符串的MD5码的方法(网上找的):

    public static String md5(String string) {
        byte[] hash;
        try {
            hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Huh, MD5 should be supported?", e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Huh, UTF-8 should be supported?", e);
        }
        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10) hex.append("0");
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString();
    }

40.当使用广播接收者时,尽量给接收者设置一个action,可以在清单文件里直接设置<intent-filter>或者代码里new IntentFilter(),在registerReceiver()时设置给广播接收者,原因        是某些手机不设置广播的action,广播接收者不一定能收到广播。

41.在通知栏点击通知跳转到app时,要先判断app是否已经启动。下面的代码可以判断app是否已经启动:

 public Boolean run() {
        /**
         * android5.0之后不能通过getrunningtask获得正在运行的任务
         */
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
            return getActivePackages();
        } else {
            return getActivePackagesCompat();
        }
    }

    /**
     * android5.0+之后判断app是否还在运行
     *
     * @return
     */
    private Boolean getActivePackages() {
        List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo info : runningAppProcesses
                ) {
            if (info.processName.equals(packagename)) {
                return true;
            }
        }
        return false;
    }

    /**
     * android5.0之前判断app是否还在运行
     *
     * @return
     */
    private Boolean getActivePackagesCompat() {
        List<ActivityManager.RunningTaskInfo> runningTasks = activityManager.getRunningTasks(100);
        for (ActivityManager.RunningTaskInfo info : runningTasks
                ) {
            if (info.topActivity.getPackageName().equals(packagename) && info.baseActivity.getPackageName().equals(packagename)
                    ) {
                return true;
            }
        }
        return false;
    }
如果app已经启动了,可以用以下代码跳转的指定的activity:

 Intent intent1 = new Intent(context.getApplicationContext(), MainActivity.class);
            intent1.addCategory(Intent.CATEGORY_LAUNCHER);
            intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent1);
这里的给intent设置的addCategory()有如下解释:

大部分手机都ok, 点击通知可以正常启动应用, 但是部分手机就不行了 (如华为P6)
经过一番折腾, 添加了下面一句, 问题就解决了: 
resultIntent.addCategory(Intent.CATEGORY_LAUNCHER);
  
原来, 应用的 "入口Activity" 必须要添加Intent.CATEGORY_LAUNCHER(值: Android.intent.category.LAUNCHER)这个Category, 否则应用就无法启动.  当应用被杀死后, 我们点击通知就是要重新启动应用, 重新启动应用就要从"入口Activity"启动, 
而我所做的项目中的MainActivity确不是 "入口Activity".  因此无法启动. 
因此你要启动应用, 而你启动的Activity有不是"入口Activity"时, 就必须给intent添加 Intent.CATEGORY_LAUNCHER  这个Category.

说明: "入口Activity" 就是App的启动入口, 可以想象为main函数, 一般命名为MainActivity, 它再manifest文件中的配置一般有这样一个<intent-filter>
<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
(最后附上这段解释的原地址: 点击打开链接

如果app没有启动,可以使用以下代码正常启动app:

Intent launchIntentForPackage = context.getApplicationContext().getPackageManager().getLaunchIntentForPackage(packagename);
            launchIntentForPackage.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
            context.startActivity(launchIntentForPackage);


42.如果要从外部打开app,比如通知栏、广播等,必须设置addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),所以也必须设置activity的启动方式为singletask,否则会导致总是启动新的app而不是回到已经打开的app.

43.清单文件中的activity的exported属性:在Activity中该属性用来标示:当前Activity是否可以被另一个Application的组件启动:true允许被启动;false不允许被启动。如果被设置为了false,那么这个Activity将只会被当前Application或者拥有同样user ID的Application的组件调用。exported 的默认值根据Activity中是否有intent filter 来定。没有任何的filter意味着这个Activity只有在详细的描述了他的class name后才能被唤醒 .这意味着这个Activity只能在应用内部使用,因为其它application并不知道这个class的存在。所以在这种情况下,它的默认值是false。从另一方面讲,如果Activity里面至少有一个filter的话,意味着这个Activity可以被其它应用从外部唤起,这个时候它的默认值是true。(这一条与41条遥相呼应)。微信的分享回调activity的exported属性设置就是true,这里如果设置为true还会有一些别问题,贴两张图:



44. BroadcastReceiver的onreceive()方法最多执行10秒钟,如果超过10秒会抛出“ANR”,当广播接收者onReceive方法需要执行很长时间时,最好将此耗时工作通过Intent发送给Service,由Service完成,并且不能使用子线程解决,因为BroadcastReceiver是接收到广播后才创建的,并且生命周期很短,因此子线程可能在没有执行完就已经被杀死了.由于只能执行10秒钟的问题所以onreceive()方法中接收到的数据,创建的变量等生命周期都很短,10秒钟后就全部为空了。(做项目时遇到一个brodcastreceiver接受2种广播,接收第一种时读取广播中的数据,解析并加工生成对象放到一个集合中并用一个notificationmanager发送通知,等接收到第二种广播时取出集合中的数据,但是发现接受第二种广播时集合和notificationmanager都为空了).

45.webview可以指定缓存的位置和大小,并且缓存和H5的缓存是分开的。

46.context.getexternalstorage()获得的是默认存储的位置并非一定是系统的sdcard,如果你将外置的sdcard设置为默认存储,则获得的就是这张插入的sdcard。

47.传递序列化的对象时,如果是内部类的对象,则内部和外部都要序列化,且如果传递装着对象的集合时只能传Parcelable的对象集合,不能传Serializable对象的集合。

48.补间动画的repeatMode属性需要和repeatCount属性一起使用才有效。而动画实际的执行次数是在repeatCount的数值上+1,因为即使没有repeatCount属性动画也至少执行一次。
 

49.在listview中用radiobutton实现单选效果,有很多种方式可以实现,我只用过2种:第一种,在adapter中使用一个整型的currentposition标示被选中项,默认值为0,在getview方法中,判断position是否等于currentposition,如果等于则这个item是被选中项,修改radiobutton的状态即可,radiobutton的点击事件里,将position替换currentposition的值,然后notifydatasetchange()就行了,listview的OnItemClickListener中,获取adapter中的currentposition的值替换为点击项的positon即可。但是这种方法有一些bug,因为偶尔会发生position错乱的问题,也不算错乱吧,就是比如只有4个item,一屏显示3个,第一次加载就加载完了4个,但是快速来回滑动时就发现第一个和第四个居然互相复用,并且加载第一个时getview中打印的position居然是3,加载第四个时getview中打印的position是0,但是加载的文本等数据又是对的,就是radiobutton的状态不对。所以推荐第二种方法,应该也是网上用的最多的方法:直接在item对应的实体类中加入一个ischecked属性来判断是否被选中,第一次显示listview时根据ischecked属性控制radiobutton的状态,在radiobutton的onclicklistener中遍历list集合,先把所有的对象的ischecked属性全部置为false,再根据position把点击的那个radiobutton的item对应对象的ischecked属性置为true,然后notifydatasetchange(),listview的OnItemClickListener中,同样先遍历集合把所有的置为false,接着根据点击的那个position修改对应item对象的ischecked属性。如果需要获得所点击项对象,可以直接遍历list集合,找到ischecked为true的,也可以遍历listview。listview.getchildAt(i).findviewbyid找到radiobutton,判断其状态,为true获取item的position.贴一些之前写的代码:

holder.enterprise_rb.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                for (SellerInfo sellerInfo :
                        list) {
                    sellerInfo.setIschecked(false);
                }
                list.get(position).setIschecked(true);
                notifyDataSetChanged();
            }
        });


dialog_lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                                @Override
                                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                                    for (SellerInfo sellerinfo :
                                            sellerinfolist) {
                                        sellerinfo.setIschecked(false);
                                    }
                                    sellerinfolist.get(position).setIschecked(true);
                                    adapter.notifyDataSetChanged();
                                }
                            });

  choose_btn.setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View v) {
                                    for (int i = 0; i < sellerinfolist.size(); i++) {
                                        if (sellerinfolist.get(i).ischecked()) {
                                            SellerInfo sellerInfo = sellerinfolist.get(i);
                                            Intent intent = new Intent(Login_Activity.this, MainActivity.class);
                                            Bundle bundle = new Bundle();
                                            bundle.putSerializable("sellerinfo", sellerInfo);
                                            intent.putExtras(bundle);
                                            startActivity(intent);
                                            Login_Activity.this.finish();
                                        }
                                    }
                                }
                            });

50.BaseAdapter中有一个可以重写的方法叫isEnable(),这个方法可以用来控制每一个item能否被点击,当返回true时表示整个item可以被点击,当返回false时表示整个item不可被点击。

51.一种新的闪屏页延迟跳转的新思路

        /**
         * 设置停顿2秒跳转到引导页或者主页面或者登录页
         */
        new Handler() {
            @Override
            public void handleMessage(android.os.Message msg) {
                if (isfirstopen) {
                    startActivity(new Intent(SplashActivity.this, GuideActivity.class));
                    ioqt_sp.edit().putBoolean("isfirstopen", false).commit();
                } else {
                    if (islogined) {
                        startActivity(new Intent(SplashActivity.this, HomeActivity.class));
                    } else {
                        startActivity(new Intent(SplashActivity.this, LoginActivity.class));
                    }
                }
                finish();
            }
        }.sendEmptyMessageDelayed(0, 2000);
52.一般用来设置验证码倒计时的方法
    /**
     * 倒计时开始的方法
     */
    private void startTimer() {
        if (timeCountDown == null) {
            timeCountDown = new TimeCountDown(120000, 1000, tv_getctfcode, "重新发送");//第一个参数为millisInFuture,倒计时的总时间,为毫秒。

        }
        timeCountDown.start();
    }
倒计时类
public class TimeCountDown extends CountDownTimer {
    private TextView view;
    private String str;

    /**
     * @param millisInFuture    The number of millis in the future from the call
     *                          to {@link #start()} until the countdown is done and {@link #onFinish()}
     *                          is called.
     * @param countDownInterval The interval along the way to receive
     *                          {@link #onTick(long)} callbacks.
     */

    public TimeCountDown(long millisInFuture, long countDownInterval, TextView view, String str) {
        super(millisInFuture, countDownInterval);
        this.view = view;
        this.str = str;
    }


    @Override
    public void onTick(long millisUntilFinished) {
        view.setClickable(false);
        view.setText(millisUntilFinished/1000 + "秒");
    }

    @Override
    public void onFinish() {
        view.setText(str);
        view.setClickable(true);
    }
}
53.picasso在加载uri时不会加上 Scheme,所以加载本地图片会失败。以下是网络上的解决方法。
Picasso所有load的重载都会将传入参数转化为Uri 再交给RequestCreator处理

而Picasso.load(localImagePath) 转化为Uri是没有 Scheme的 uri: "/storage/emulated/0/Android/data/xxxx/xxx.png"
这样当然无法解析图片了

解决方式:
Picasso.load(new File(localImagePath)) 就可以了,File转化为Uri 是包含Scheme的,
uri: "file:///storage/emulated/0/Android/data/xxxxx/xxx.png"
54.okhttp同时上传文件和表单参数
 private void modifyUserMessage() {
        OkHttpClient okHttpClient = new OkHttpClient();
        //FORM表单形式上传
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
        if (TextUtils.isEmpty(url)) {
            File file = new File(url);
            RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
            // 参数分别为, 服务端请求key ,文件名称 , RequestBody
            builder.addFormDataPart("image", file.getName(), requestBody);
        }
        if (map != null) {
            // map 里面是请求中所需要的 key 和 value
            for (Map.Entry entry : map.entrySet()) {
                builder.addFormDataPart(entry.getKey().toString(), entry.getValue().toString());
            }
        }
        Request request = new Request.Builder().url(BaseUrl.BASE_URL + BaseUrl.MODIFYUSERMESSAGE_URL).post(builder.build()).build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                CustomToast.ShowShortToast(Cpt_userinfoActivity.this, e + "");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String s = response.body().string();
                CustomToast.ShowShortToast(Cpt_userinfoActivity.this, "" + s);
            }
        });

    }

55.用intent直接传递对象

 Intent intent = new Intent();
 intent.putExtra("data", data); //这个data对象必须序列化,如果是内部类的对象则内部类和外部类都必须序列化,且若传装着对象的集合则只能parceable
//获取传递过来的对象
 RegisterUser.DataBean dataBean = (RegisterUser.DataBean) data.getSerializableExtra("data");

56.用bundle传递对象

 Intent intent = new Intent();
 Bundle bundle = new Bundle();
 bundle.putSerializable("postsListItem", postsListItem);
 intent.putExtras(bundle);

//获取传递过来的对象
  Bundle bundle = data.getExtras();
  PostsListItem postsListItem = (PostsListItem) bundle.getSerializable("postsListItem");


57.edittext.clearfocus()可以让edittext失去焦点,当edittext失去焦点时,输入法会自动关闭。

58.使用compile 'com.jcodecraeer:xrecyclerview:1.3.2'时要注意各个position。

@Override  
 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {  
     Log.d("bug", "Adapter   " + holder.getAdapterPosition() + "   Layout   " + holder.getLayoutPosition() + "  position  " + position);  
 }  
//原生的recyclerview
Adapter   0   Layout   0  position  0  
Adapter   1   Layout   1  position  1  
Adapter   2   Layout   2  position  2  
Adapter   3   Layout   3  position  3  
//xrecyclerview
Adapter   1   Layout   1  position  0  
Adapter   2   Layout   2  position  1  
Adapter   3   Layout   3  position  2  
Adapter   4   Layout   4  position  3  
//xrecyclerview的position是正常的,但是另外2种方式获得position都+1了。
59.recyclerview点击事件具体实现
/**
     * 2.声明接口变量
     */
    private OnItemClickListener mItemClickListener;

    /**
     * 1.定义接口
     */
    public interface OnItemClickListener {
        public void onItemClickListener(int position);

        public void onItemLongClickListener(int position);
    }

    /**
     * 3.初始化接口变量
     *
     * @param mItemClickListener
     */
    public void setmItemClickListener(OnItemClickListener mItemClickListener) {
        this.mItemClickListener = mItemClickListener;
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        PostsListItem postsListItem = list.get(position);
        Picasso.with(context).load(postsListItem.getUserimg()).transform(new CircleTransform()).into(holder.iv_userimg);
//        holder.iv_userimg.setImageResource(postsListItem.getUserimg());
        holder.tv_username.setText(postsListItem.getUsername());
        holder.tv_contenttitle.setText(postsListItem.getContenttitle());
        holder.iv_content.setImageResource(postsListItem.getContentimg());
        holder.tv_content.setText(postsListItem.getContent());
        if (mItemClickListener != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mItemClickListener.onItemClickListener(position);
                }
            });
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    mItemClickListener.onItemLongClickListener(position);
                    return true;
                }
            });
        }
    }
//或者在ViewHolder类里面写
            if (mItemClickListener != null) {
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        mItemClickListener.onItemClickListener(getLayoutPosition());
                    }
                });
                itemView.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View view) {
                        mItemClickListener.onItemLongClickListener(getLayoutPosition());
                        CustomToast.ShowShortToast(context, getLayoutPosition() + "");
                        return true;
                    }
                });
            }
不建议在bindviewholder里面写的原因是删除item如果使用的是notifydataremove(),则position不会立马改变,后面的item依然是删除之前的position,要等到notifydatasetchange()才会变,但如果在ViewHolder里写的,则获取的其实是getlayoutposition(),原生的recyclerview会立马改变position,而不用等到notifydatasetchange().

60.遍历map集合的两种方式:

//第一种方式
  Set keys = map.keySet( );
       if(keys != null)
          for(String s : keys)
获得一个包含所有key的集合,然后for循环取出所有的key,再从map集合中根据key取出value.

第二种方式
 for(Map.Entry entry : map.entrySet()) {
        }
使用此种方法必须指定map集合的key和value的数据类型,entry就是map集合中的一对对键值对,entry.getkey和entry.getvalue可以分别取出key和value。

61.android页面进入edittext自动获取焦点,弹出软键盘解决方法
//在edittext的父布局中加入上面2个属性
android:focusable="true"
android:focusableInTouchMode="true"


62.在LineraLayout中,当设置Android:orientation="horizental" ,子控件的android:layout_gravity="left",android:layout_gravity="right"是无效的,但可以用一下方法达到2个控件分别居左和居右的效果。
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
/>
</LinearLayout>
设置 android:layout_width="0dp",android:layout_height="wrap_content",android:layout_weight="1"这三个属性后,就会把match_parent剩下的布局给撑满,所以会把右边那个textView挤到最右端。这样就能达到在LinLinearLayout中水平方向上的有两个textview一个居左,一个居右的效果。

63.某些时候自动隐藏导航栏,亮点在于自动改变布局大小,不会覆盖,在OnCreate方法中使用:myview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)其中的myview 可以为Layout中任意的一个View对象(可以由findViewById得到)。此时该Activity显示时会自动隐藏Navigation Bar,但有触摸事件时重新显现Navigation Bar。屏幕的Layout会自动收缩适应新的屏幕大小。

64.另外一种隐藏导航栏的方式:

    /**
     * 隐藏导航栏
     *
     * @param activity 当前Activity
     */
    public static void hideNavigationBar(Activity activity) {
        int uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN;

        if (android.os.Build.VERSION.SDK_INT >= 19) {
            uiFlags |= 0x00001000;
        } else {
            uiFlags |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
        }
        activity.getWindow().getDecorView().setSystemUiVisibility(uiFlags);
    }
这种方式不会挤压布局,而是会让导航栏覆盖在布局上面。并且在Activity中还要重写:
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            SystemUtil.hideNavigationBar(this);
        }
    }
不然的话,下拉通知栏或弹出对话框后,导航栏不会隐藏。










  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值