[Android] gradient中设置angle角度问题

在设置gradient时,经常需要设置角度,android:angle=”90″,比如:

<shape
xmlns:android=”http://schemas.android.com/apk/res/android”
android:shape=”rectangle”>
<gradient
android:startColor=”@color/mainPinkStart”
android:endColor=”@color/mainPinkEnd”
android:angle=”90″ />
</shape>

这里需要注意的是,angle值只能是45的倍数,否则会出现下面的错误log:

Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #5<gradient> tag requires ‘angle’ attribute to be a multiple of 45
at android.graphics.drawable.GradientDrawable.updateGradientDrawableGradient(GradientDrawable.java:1354)
at android.graphics.drawable.GradientDrawable.inflateChildElements(GradientDrawable.java:1176)

[Android] FragmentPagerAdapter or FragmentStatePageAdapter获取Fragment

ViewPager和Fragment搭配使用,是很多APP经常采用的方法,但其中有很多“坑”要注意。比如这里有个需求,需要获取某个Fragment的实例,来进行一些操作。这里又分FragmentPagerAdapter 和 FragmentStatePageAdapter,两者区别见

1.对于FragmentPagerAdapter,经常用的是

"android:switcher:" + viewId + ":" + position

2.对于FragmentStatePageAdapter,不支持上面方式,这里有个简单的办法:

myFragmentStatePageAdpater.instantiateItem(null, position)

参考:http://stackoverflow.com/questions/12384971/android-fragmentstatepageradapter-how-to-tag-a-fragment-to-find-it-later

http://stackoverflow.com/questions/14035090/how-to-get-existing-fragments-when-using-fragmentpageradapter#

http://stackoverflow.com/questions/8785221/retrieve-a-fragment-from-a-viewpager

[Android] FragmentPagerAdapter 和 FragmentStatePageAdapter区别

一、官方解释

FragmentPagerAdapter 

This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page the user visits will be kept in memory, though its view hierarchy may be destroyed when not visible. This can result in using a significant amount of memory since fragment instances can hold on to an arbitrary amount of state. For larger sets of pages, consider FragmentStatePagerAdapter.

FragmentStatePageAdapter

This version of the pager is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.

二、通俗解释

1. 适用对象:

FragmentPagerAdapter适用static and less count数目Fragment

FragmentStatePageAdapter适用dynamic and more count数目Fragment

2. Fragment生命周期

FragmentPagerAdapter中的Fragment是Detached,即,仅仅是对应的View被回收,整个Fragment实例仍然存在。

FragmentStatePageAdapter中的Fragment是Removed/Destroyed,整个Fragment实例都被回收干掉。

3. 内存占用

FragmentPagerAdapter占用内存大,因为Fragment实例仍然存在。

FragmentStatePageAdapter不占用内存,但它并不是永远消失了,从名字中的State可以看出,系统会把Fragment的state作为Bundle通过savedInstanceState而保存下来,当我们重新回到该Fragment后,可以从onViewStateRestored中恢复。

参考:http://stackoverflow.com/questions/30235335/difference-between-fragmentpageradapter-with-viewpager-with-offscreenlimit-set-t

[Android] TextView中setPadding()方法失效,不起作用

项目中使用了一个第三方控件,很多人都有用过,PagerSlidingTabStrip,发现在4.4(Kitkat)之前的版本,每个tab会挤在一起,分析源码后,发现每个tab在设置了setPadding后根本就无效,网上一查,还真有坑。

原因是在每个tab调用了setPadding后,又在其他地方调用了setBackgroundResource(),这在4.4之前是有问题的,4.4及以后的版本google已经fix了这个bug。

// does not work
tv.setPadding(20, 20, 20, 20);
tv.setBackgroundResource(R.drawable.border);

// works
tv.setBackgroundResource(R.drawable.border);
tv.setPadding(20, 20, 20, 20);

所以,解决办法是,必须在setBackgroundResource之后调用setPadding()方法。

[Android]Service可以显示对话框?

嗯,总有一些莫名其妙的需求,不过,仔细一想,这种情况还是存在的,比如手机电量低时,会弹出一个警告对话框,还有闹钟也会弹对话框,好,那就看看怎么来实现吧。

1.让service启动一个activity,该activity实际上是一个dialog类型,设置theme如下:

android:theme="@android:style/Theme.Dialog"

有个开源项目android-smspopup就是用的这个方法。

2.不使用activity

AlertDialog alertDialog = new AlertDialog.Builder(this)
                    .setTitle("Title")
                    .setMessage("Are you sure?")
                    .create();

alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();

在manifest里要用到一个权限:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

3. 基本上以上两个办法就可以了,更详细的讨论可以参考下这篇文章

 

Android自定义View实现左右滑动选择出生年份

转自:http://www.jb51.net/article/86071.htm

模仿的是微博运动界面的个人出生日期设置view,先看看我的效果图:

支持设置初始年份,左右滑动选择出生年份,对应的TextView的值也会改变。这个动画效果弄了好久,感觉还是比较生硬,与微博那个还是有点区别。大家有改进的方案,欢迎一起交流。

自定义View四部曲,这里依旧是这个套路,看看怎么实现的。

1.自定义view的属性:
在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性以及声明我们的整个样式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<resources>
 //自定义属性名,定义公共属性
 <attr name="titleSize" format="dimension"></attr>
 <attr name="titleText" format="string"></attr>
 <attr name="titleColor" format="color"></attr>
 <attr name="outCircleColor" format="color"></attr>
 <attr name="inCircleColor" format="color"></attr>
 <attr name="lineColor" format="color"></attr>
 <declare-styleable name="MyScrollView">
  <attr name="titleSize"></attr>
  <attr name="titleColor"></attr>
  <attr name="lineColor"></attr>
 </declare-styleable>
</resources>

依次定义了字体大小,字体颜色,线的颜色3个属性,format是值该属性的取值类型。
然后就是在布局文件中申明我们的自定义view:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<TextView
 android:id="@+id/year_txt"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_margin="30dp"
 android:text="出生年份 (年)"
 android:textSize="20dp" />
<com.example.tangyangkai.myview.MyScrollView
 android:id="@+id/scroll_view"
 android:layout_width="match_parent"
 android:layout_height="70dp"
 myscroll:lineColor="@color/font_text"
 myscroll:titleColor="@color/strong"
 myscroll:titleSize="30dp">
</com.example.tangyangkai.myview.MyScrollView>

自定义view的属性我们可以自己进行设置,记得最后要引入我们的命名空间,
xmlns:app=”http://schemas.Android.com/apk/res-auto”

2.获取自定义view的属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public MyScrollView(Context context) {
 this(context, null);
}
public MyScrollView(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
}
public MyScrollView(final Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 //获取我们自定义的样式属性
 TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyScrollView, defStyleAttr, 0);
 int n = array.getIndexCount();
 for (int i = 0; i < n; i++) {
  int attr = array.getIndex(i);
  switch (attr) {
   case R.styleable.MyScrollView_lineColor:
    // 默认颜色设置为黑色
    lineColor = array.getColor(attr, Color.BLACK);
    break;
   case R.styleable.MyScrollView_titleColor:
    textColor = array.getColor(attr, Color.BLACK);
    break;
   case R.styleable.MyScrollView_titleSize:
    // 默认设置为16sp,TypeValue也可以把sp转化为px
    textSize = array.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
      TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
    break;
  }
 }
 array.recycle();
 init();
}
private void init() {
 //初始化
 mPaint = new Paint();
 mPaint.setAntiAlias(true);
 mBound = new Rect();
 mTxtBound = new Rect();
 bigTxtSize = textSize;
 oneSize = textSize - 15;
 thirdSize = textSize - 15;
}

自定义View一般需要实现一下三个构造方法,这三个构造方法是一层调用一层的,属于递进关系。因此,我们只需要在最后一个构造方法中来获得View的属性以及进行一些必要的初始化操作。尽量不要在onDraw的过程中去实例化对象,因为这是一个频繁重复执行的过程,new是需要分配内存空间的,如果在一个频繁重复的过程中去大量地new对象会造成内存浪费的情况。

3.重写onMesure方法确定view大小:

上一篇自定义View的文章介绍的很详细,这里就不重复了,重点放在onDraw方法里面:
Android自定义View仿微博运动积分动画效果

4.重写onDraw方法进行绘画:

之前说过对于比较复杂的自定义View,重写onDraw方法之前,首先在草稿本上将大致的样子画出来,坐标,起始点都可以简单标注一下。这个方法很实用,思路很清晰。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
 int action = ev.getAction();
 int x = (int) ev.getX();
 int y = (int) ev.getY();
 switch (action) {
  case MotionEvent.ACTION_DOWN:
   xDown = x;
   yDown = y;
   break;
  case MotionEvent.ACTION_MOVE:
   xMove = x;
   yMove = y;
   dx = xMove - xDown;
   int dy = yMove - yDown;
   //如果是从左向右滑动
   if (xMove > xDown && Math.abs(dx) > mTouchSlop * 2 && Math.abs(dy) < mTouchSlop) {
    state = 1;
   }
   //如果是从右向左滑动
   if (xMove < xDown && Math.abs(dx) > mTouchSlop * 2 && Math.abs(dy) < mTouchSlop) {
    state = 2;
   }
   break;
  case MotionEvent.ACTION_UP:
   break;
 }
 return super.dispatchTouchEvent(ev);
}

重写View的dispatchTouchEvent方法来区别左右滑动,mTouchSlop是Android默认的滑动最小距离,如果水平方向滑动的距离大于竖直方向滑动的距离,就判断为水平滑动。这里为了不让滑动那么明显,我让水平滑动的距离大于默认距离的两倍才判定左右滑动。state是记录滑动的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Override
public boolean onTouchEvent(MotionEvent ev) {
 int action = ev.getAction();
 switch (action) {
  case MotionEvent.ACTION_DOWN:
   break;
  case MotionEvent.ACTION_MOVE:
   if (state == 1 && bigTxtSize - oneSize > -15) {
    bigTxtSize = bigTxtSize - 1;
    oneSize = oneSize + 1;
    postInvalidate();
   }
   if (state == 2 && bigTxtSize - thirdSize > -15) {
    bigTxtSize = bigTxtSize - 1;
    thirdSize = thirdSize + 1;
    postInvalidate();
   }
   break;
  case MotionEvent.ACTION_UP:
   if (state == 1) {
    size = size - 1;
    bigTxtSize = textSize;
    oneSize = textSize - 15;
    postInvalidate();
    listener.OnScroll(size);
    state = 0;
   }
   if (state == 2) {
    size = size + 1;
    bigTxtSize = textSize;
    thirdSize = textSize - 15;
    postInvalidate();
    listener.OnScroll(size);
    state = 0;
   }
   break;
 }
 return true;
}

重写View的onTouchEvent方法来处理View的点击事件。
(1)演示动态图中,左右滑动的过程中,中间数字会从大变小,左右的数字会从小变大,bigTxtSize代表中间的数字大小,oneSize代表从左到右第二个数字的大小,thirdSize代表从左到右第四个数字的大小。在滑动过程中再使用postInvalidate()方法来一直调用onDraw方法来重新进行绘制,达到数字大小变化的效果。
(2)滑动结束以后进行判断,如果是从左向右滑动,就会将数字减一;如果是从右向左滑动,就会将数字加一。最后将数字大小,滑动状态恢复到默认值。
(3)最后一定要返回true,表示消费当前滑动事件,不然滑动没反应

滑动的操作已经全部处理好,接下来就是绘制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@Override
protected void onDraw(Canvas canvas) {
 txtSize = size - 2;
 bigText = String.valueOf(size);
 smallText = String.valueOf(txtSize);
 mPaint.setColor(lineColor);
 canvas.drawLine(0, 0, getWidth(), 0, mPaint);
 canvas.drawLine(0, getHeight(), getWidth(), getHeight(), mPaint);
 lineX = getWidth() / 10;
 for (int i = 0; i < 5; i++) {
  if (i == 2) {
   mPaint.setTextSize(bigTxtSize);
   if (bigTxtSize == textSize - 15) {
    mPaint.setColor(lineColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 5, mPaint);
   } else {
    mPaint.setColor(textColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 3, mPaint);
   }
   mPaint.getTextBounds(bigText, 0, bigText.length(), mBound);
   canvas.drawText(bigText, lineX - mBound.width() / 2, getHeight() / 2 + mBound.height() * 3 / 4, mPaint);
  } else if (i == 0 || i == 4) {
   mPaint.setColor(lineColor);
   mPaint.setTextSize(textSize - 15);
   mPaint.getTextBounds(smallText, 0, smallText.length(), mTxtBound);
   canvas.drawLine(lineX, 0, lineX, getHeight() / 5, mPaint);
   canvas.drawText(String.valueOf(txtSize), lineX - mTxtBound.width() / 2, getHeight() / 2 + mTxtBound.height() * 3 / 4, mPaint);
  } else if (i == 1) {
   mPaint.setTextSize(oneSize);
   if (oneSize == textSize) {
    mPaint.setColor(textColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 3, mPaint);
   } else {
    mPaint.setColor(lineColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 5, mPaint);
   }
   mPaint.getTextBounds(smallText, 0, smallText.length(), mTxtBound);
   canvas.drawText(String.valueOf(txtSize), lineX - mTxtBound.width() / 2, getHeight() / 2 + mTxtBound.height() * 3 / 4, mPaint);
  } else {
   mPaint.setTextSize(thirdSize);
   if (thirdSize == textSize) {
    mPaint.setColor(textColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 3, mPaint);
   } else {
    mPaint.setColor(lineColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 5, mPaint);
   }
   mPaint.getTextBounds(smallText, 0, smallText.length(), mTxtBound);
   canvas.drawText(String.valueOf(txtSize), lineX - mTxtBound.width() / 2, getHeight() / 2 + mTxtBound.height() * 3 / 4, mPaint);
  }
  txtSize++;
  lineX += getWidth() / 5;
 }
}

这里其实就是得到滑动操作的数字尺寸大小,然后进行绘制,最后将数字每次加一,lineX是B点的初始位置,每次加上宽度的五分之一。

5.得到当前的设置值
可以看到View上面的TextView也会跟着下面设置的值改变,所以这里我们需要单独处理一下。接口回调,简单暴力的方式。

在onTouchEvent的case MotionEvent.ACTION_UP中,得到最后设置的值

listener.OnScroll(size);

然后就是对应的Activity了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class SecondActivity extends AppCompatActivity implements MyScrollView.OnScrollListener {
 private MyScrollView scrollView;
 private TextView txt;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_second);
  initview();
 }
 private void initview() {
  scrollView = (MyScrollView) findViewById(R.id.scroll_view);
  scrollView.setSize(1992);
  scrollView.setListener(this);
  txt = (TextView) findViewById(R.id.year_txt);
  txt.setText("出生年份" + scrollView.getSize() + " (年)");
 }
 @Override
 public void OnScroll(int size) {
  txt.setText("出生年份" + size + " (年)");
 }
}

实现接口的方法,进行初始化,设置初始值,然后就是在接口的方法更新数据即可。

[Andorid]网络IO应该在哪种形式的线程中执行

网络IO应该在哪种形式的线程中执行

  • 首先网络IO一般耗时比较长,有的可能到几十毫秒
  • 由于耗时较长,如果采用单一线程处理,势必导致后续的请求无法快速执行
  • 建议使用线程池来处理达到快速响应和线程的复用。

简单示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void testDoNetworkRequest() {
    int corePoolSize = 5;
    int maxPoolSize = 10;
    //线程数量超过核心线程数之后的超时时间,即超过这个时间还没有新的task,多余的线程则销毁掉。
    long keepAliveTime = 10;
    ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());

    executor.execute(new Runnable() {
        @Override
        public void run() {
            //Do network IO here
        }
    });
}

关于线程的文章,请参考

Android有用的代码集合

代码地址:https://github.com/Blankj/AndroidUtilCode/tree/master/utilcode/src/main/java/com/blankj/utilcode/utils

为方便查找,已进行大致归类,其目录如下所示:

  • Activity相关→ActivityUtils.java
    isActivityExists : 判断是否存在Activity
    launchActivity   : 打开Activity
  • App相关→AppUtils.java
    isInstallApp          : 判断App是否安装
    installApp            : 安装App(支持6.0)
    installAppSilent      : 静默安装App
    uninstallApp          : 卸载App
    uninstallAppSilent    : 静默卸载App
    launchApp             : 打开App
    getAppPackageName     : 获取App包名
    getAppDetailsSettings : 获取App具体设置
    getAppName            : 获取App名称
    getAppIcon            : 获取App图标
    getAppPath            : 获取App路径
    getAppVersionName     : 获取App版本号
    getAppVersionCode     : 获取App版本码
    getAppSignature       : 获取App签名
    getAppSignatureSHA1   : 获取应用签名的的SHA1值
    isSystemApp           : 判断App是否是系统应用
    isAppForeground       : 判断App是否处于前台
    getAppInfo            : 获取App信息
    getAppsInfo           : 获取所有已安装App信息
    cleanAppData          : 清除App所有数据
  • 栏相关→BarUtils.java
    setTransparentStatusBar : 设置透明状态栏(api大于19方可使用)
    hideStatusBar           : 隐藏状态栏
    getStatusBarHeight      : 获取状态栏高度
    isStatusBarExists       : 判断状态栏是否存在
    getActionBarHeight      : 获取ActionBar高度
    showNotificationBar     : 显示通知栏
    hideNotificationBar     : 隐藏通知栏
  • 清除相关→CleanUtils.java
    cleanInternalCache    : 清除内部缓存
    cleanInternalFiles    : 清除内部文件
    cleanInternalDbs      : 清除内部数据库
    cleanInternalDbByName : 根据名称清除数据库
    cleanInternalSP       : 清除内部SP
    cleanExternalCache    : 清除外部缓存
    cleanCustomCache      : 清除自定义目录下的文件
  • 剪贴板相关→ClipboardUtils.java
    copyText   : 复制文本到剪贴板
    getText    : 获取剪贴板的文本
    copyUri    : 复制uri到剪贴板
    getUri     : 获取剪贴板的uri
    copyIntent : 复制意图到剪贴板
    getIntent  : 获取剪贴板的意图
  • 关闭相关→CloseUtils.java
    closeIO        : 关闭IO
    closeIOQuietly : 安静关闭IO
  • 常量相关→ConstUtils.java
    MemoryConst : 存储相关常量
    TimeConst   : 时间相关常量
    RegexConst  : 正则相关常量
  • 转换相关→ConvertUtils.javaTest
    bytes2HexString, hexString2Bytes         : byteArr与hexString互转
    chars2Bytes, bytes2Chars                 : charArr与byteArr互转
    byte2Size, size2Byte                     : 字节数与unit为单位的size互转
    byte2FitSize                             : 字节数转合适大小
    bytes2Bits, bits2Bytes                   : bytes与bits互转
    input2OutputStream, output2InputStream   : inputStream与outputStream互转
    inputStream2Bytes, bytes2InputStream     : inputStream与byteArr互转
    outputStream2Bytes, bytes2OutputStream   : outputStream与byteArr互转
    inputStream2String, string2InputStream   : inputStream与string按编码互转
    outputStream2String, string2OutputStream : outputStream与string按编码互转
    bitmap2Bytes, bytes2Bitmap               : bitmap与byteArr互转
    drawable2Bitmap, bitmap2Drawable         : drawable与bitmap互转
    drawable2Bytes, bytes2Drawable           : drawable与byteArr互转
    view2Bitmap                              : view转Bitmap
    dp2px, px2dp                             : dp与px互转
    sp2px, px2sp                             : sp与px互转
  • 崩溃相关→CrashUtils.java
    getInstance : 获取单例
    init        : 初始化
  • 设备相关→DeviceUtils.java
    isRoot          : 判断设备是否root
    getSDKVersion   : 获取设备系统版本号
    getAndroidID    : 获取设备AndroidID
    getMacAddress   : 获取设备MAC地址
    getManufacturer : 获取设备厂商,如Xiaomi
    getModel        : 获取设备型号,如MI2SC
  • 判空相关→EmptyUtils.javaTest
    isEmpty    : 判断对象是否为空
    isNotEmpty : 判断对象是否非空
  • 编码解码相关→EncodeUtils.javaTest
    urlEncode                         : URL编码
    urlDecode                         : URL解码
    base64Encode, base64Encode2String : Base64编码
    base64Decode                      : Base64解码
    base64UrlSafeEncode               : Base64URL安全编码
    htmlEncode                        : Html编码
    htmlDecode                        : Html解码
  • 加密解密相关→EncryptUtils.javaTest
    encryptMD2, encryptMD2ToString                         : MD2加密
    encryptMD5, encryptMD5ToString                         : MD5加密
    encryptMD5File, encryptMD5File2String                  : MD5加密文件
    encryptSHA1, encryptSHA1ToString                       : SHA1加密
    encryptSHA224, encryptSHA224ToString                   : SHA224加密
    encryptSHA256, encryptSHA256ToString                   : SHA256加密
    encryptSHA384, encryptSHA384ToString                   : SHA384加密
    encryptSHA512, encryptSHA512ToString                   : SHA512加密
    encryptHmacMD5, encryptHmacMD5ToString                 : HmacMD5加密
    encryptHmacSHA1, encryptHmacSHA1ToString               : HmacSHA1加密
    encryptHmacSHA224, encryptHmacSHA224ToString           : HmacSHA224加密
    encryptHmacSHA256, encryptHmacSHA256ToString           : HmacSHA256加密
    encryptHmacSHA384, encryptHmacSHA384ToString           : HmacSHA384加密
    encryptHmacSHA512, encryptHmacSHA512ToString           : HmacSHA512加密
    encryptDES, encryptDES2HexString, encryptDES2Base64    : DES加密
    decryptDES, decryptHexStringDES, decryptBase64DES      : DES解密
    encrypt3DES, encrypt3DES2HexString, encrypt3DES2Base64 : 3DES加密
    decrypt3DES, decryptHexString3DES, decryptBase64_3DES  : 3DES解密
    encryptAES, encryptAES2HexString, encryptAES2Base64    : AES加密
    decryptAES, decryptHexStringAES, decryptBase64AES      : AES解密
  • 文件相关→FileUtils.javaTest
    getFileByPath             : 根据文件路径获取文件
    isFileExists              : 判断文件是否存在
    isDir                     : 判断是否是目录
    isFile                    : 判断是否是文件
    createOrExistsDir         : 判断目录是否存在,不存在则判断是否创建成功
    createOrExistsFile        : 判断文件是否存在,不存在则判断是否创建成功
    createFileByDeleteOldFile : 判断文件是否存在,存在则在创建之前删除
    copyDir                   : 复制目录
    copyFile                  : 复制文件
    moveDir                   : 移动目录
    moveFile                  : 移动文件
    deleteDir                 : 删除目录
    deleteFile                : 删除文件
    listFilesInDir            : 获取目录下所有文件
    listFilesInDir            : 获取目录下所有文件包括子目录
    listFilesInDirWithFilter  : 获取目录下所有后缀名为suffix的文件
    listFilesInDirWithFilter  : 获取目录下所有后缀名为suffix的文件包括子目录
    listFilesInDirWithFilter  : 获取目录下所有符合filter的文件
    listFilesInDirWithFilter  : 获取目录下所有符合filter的文件包括子目录
    searchFileInDir           : 获取目录下指定文件名的文件包括子目录
    writeFileFromIS           : 将输入流写入文件
    writeFileFromString       : 将字符串写入文件
    getFileCharsetSimple      : 简单获取文件编码格式
    getFileLines              : 获取文件行数
    readFile2List             : 指定编码按行读取文件到List
    readFile2SB               : 指定编码按行读取文件到StringBuilder中
    getFileSize               : 获取文件大小
    getFileMD5                : 获取文件的MD5校验码
    getDirName                : 根据全路径获取最长目录
    getFileName               : 根据全路径获取文件名
    getFileNameNoExtension    : 根据全路径获取文件名不带拓展名
    getFileExtension          : 根据全路径获取文件拓展名
  • 图片相关→ImageUtils.java
    bitmap2Bytes, bytes2Bitmap       : bitmap与byteArr互转
    drawable2Bitmap, bitmap2Drawable : drawable与bitmap互转
    drawable2Bytes, bytes2Drawable   : drawable与byteArr互转
    getBitmap                        : 获取bitmap
    scale                            : 缩放图片
    clip                             : 裁剪图片
    skew                             : 倾斜图片
    rotate                           : 旋转图片
    getRotateDegree                  : 获取图片旋转角度
    toRound                          : 转为圆形图片
    toRoundCorner                    : 转为圆角图片
    fastBlur                         : 快速模糊
    renderScriptBlur                 : renderScript模糊图片
    stackBlur                        : stack模糊图片
    addFrame                         : 添加颜色边框
    addReflection                    : 添加倒影
    addTextWatermark                 : 添加文字水印
    addImageWatermark                : 添加图片水印
    toAlpha                          : 转为alpha位图
    toGray                           : 转为灰度图片
    save                             : 保存图片
    isImage                          : 根据文件名判断文件是否为图片
    getImageType                     : 获取图片类型
    compressByScale                  : 按缩放压缩
    compressByQuality                : 按质量压缩
    compressBySampleSize             : 按采样大小压缩
  • 意图相关→IntentUtils.java
    getInstallAppIntent         : 获取安装App(支持6.0)的意图
    getUninstallAppIntent       : 获取卸载App的意图
    getLaunchAppIntent          : 获取打开App的意图
    getAppDetailsSettingsIntent : 获取App具体设置的意图
    getShareTextIntent          : 获取分享文本的意图
    getShareImageIntent         : 获取分享图片的意图
    getComponentIntent          : 获取其他应用组件的意图
    getShutdownIntent           : 获取关机的意图
    getCaptureIntent            : 获取拍照的意图
  • 键盘相关→KeyboardUtils.java
    hideSoftInput                 : 动态隐藏软键盘
    clickBlankArea2HideSoftInput0 : 点击屏幕空白区域隐藏软键盘(注释萌萌哒)
    showSoftInput                 : 动态显示软键盘
    toggleSoftInput               : 切换键盘显示与否状态
    isShowSoftInput               : 判断键盘是否显示
  • 日志相关→LogUtils.javaTest
    init       : 初始化函数
    getBuilder : 获取LogUtils建造者
    v          : Verbose日志
    d          : Debug日志
    i          : Info日志
    w          : Warn日志
    e          : Error日志
  • 网络相关→NetworkUtils.java
    openWirelessSettings               : 打开网络设置界面
    isAvailable                        : 判断网络是否可用
    isConnected                        : 判断网络是否连接
    is4G                               : 判断网络是否是4G
    isWifiConnected                    : 判断wifi是否连接状态
    getNetworkOperatorName             : 获取移动网络运营商名称
    getPhoneType                       : 获取移动终端类型
    getNetWorkType, getNetWorkTypeName : 获取当前的网络类型(WIFI, 2G, 3G, 4G)
  • 手机相关→PhoneUtils.java
    isPhone           : 判断设备是否是手机
    getIMEI           : 获取IMIE码
    getIMSI           : 获取IMSI码
    getPhoneStatus    : 获取手机状态信息
    dial              : 跳至填充好phoneNumber的拨号界面
    call              : 拨打phoneNumber
    sendSms           : 发送短信
    getAllContactInfo : 获取手机联系人
    getContactNum     : 打开手机联系人界面点击联系人后便获取该号码(注释萌萌哒)
    getAllSMS         : 获取手机短信并保存到xml
  • 正则相关→RegexUtils.javaTest
    isMobileSimple : 验证手机号(简单)
    isMobileExact  : 验证手机号(精确)
    isTel          : 验证电话号码
    isIDCard15     : 验证身份证号码15位
    isIDCard18     : 验证身份证号码18位
    isEmail        : 验证邮箱
    isURL          : 验证URL
    isChz          : 验证汉字
    isUsername     : 验证用户名
    isDate         : 验证yyyy-MM-dd格式的日期校验,已考虑平闰年
    isIP           : 验证IP地址
    isMatch        : string是否匹配regex
  • 屏幕相关→ScreenUtils.java
    getDeviceWidth, getDeviceHeight                 : 获取手机分辨率
    setTransparentStatusBar                         : 设置透明状态栏(api大于19方可使用)
    hideStatusBar                                   : 隐藏状态栏(注释萌萌哒)
    getStatusBarHeight                              : 获取状态栏高度
    isStatusBarExists                               : 判断状态栏是否存在
    getActionBarHeight                              : 获取ActionBar高度
    showNotificationBar                             : 显示通知栏
    hideNotificationBar                             : 隐藏通知栏
    setLandscape                                    : 设置屏幕为横屏(注释萌萌哒)
    snapShotWithStatusBar, snapShotWithoutStatusBar : 获取屏幕截图
    isScreenLock                                    : 判断是否锁屏
  • SD卡相关→SDCardUtils.java
    isSDCardEnable : 判断SD卡是否可用
    getDataPath    : 获取SD卡Data路径
    getSDCardPath  : 获取SD卡路径
    getFreeSpace   : 计算SD卡的剩余空间
    getSDCardInfo  : 获取SD卡信息
  • 服务相关→ServiceUtils.java
    isRunningService : 获取服务是否开启
  • Shell相关→ShellUtils.java
    isRoot  : 判断设备是否root
    execCmd : 是否是在root下执行命令
  • 尺寸相关→SizeUtils.java
    dp2px, px2dp     : dppx转换
    sp2px, px2sp     : sppx转换
    applyDimension   : 各种单位转换
    forceGetViewSize : 在onCreate()即可强行获取View的尺寸
    measureView      : ListView中提前测量View尺寸(注释萌萌哒)
  • SP相关→SPUtils.javaTest
    SPUtils    : SPUtils构造函数
    putString  : SP中写入String类型value
    getString  : SP中读取String
    putInt     : SP中写入int类型value
    getInt     : SP中读取int
    putLong    : SP中写入long类型value
    getLong    : SP中读取long
    putFloat   : SP中写入float类型value
    getFloat   : SP中读取float
    putBoolean : SP中写入boolean类型value
    getBoolean : SP中读取boolean
    getAll     : SP中获取所有键值对
    remove     : SP中移除该key
    contains   : SP中是否存在该key
    clear      : SP中清除所有数据
  • 字符串相关→StringUtils.javaTest
    isEmpty          : 判断字符串是否为null或长度为0
    isSpace          : 判断字符串是否为null或全为空格
    null2Length0     : null转为长度为0的字符串
    length           : 返回字符串长度
    upperFirstLetter : 首字母大写
    lowerFirstLetter : 首字母小写
    reverse          : 反转字符串
    toDBC            : 转化为半角字符
    toSBC            : 转化为全角字符
    getPYFirstLetter : 获得第一个汉字首字母
    cn2PY            : 中文转拼音
  • 线程池相关→ThreadPoolUtils.java
    ThreadPoolUtils                               : ThreadPoolUtils构造函数
    execute                                       : 在未来某个时间执行给定的命令
    execute                                       : 在未来某个时间执行给定的命令链表
    shutDown                                      : 待以前提交的任务执行完毕后关闭线程池
    shutDownNow                                   : 试图停止所有正在执行的活动任务
    isShutDown                                    : 判断线程池是否已关闭
    isTerminated                                  : 关闭线程池后判断所有任务是否都已完成
    awaitTermination                              : 请求关闭、发生超时或者当前线程中断
    submit                                        : 提交一个Callable任务用于执行
    submit                                        : 提交一个Runnable任务用于执行
    invokeAll, invokeAny                          : 执行给定的任务
    schedule                                      : 延迟执行Runnable命令
    schedule                                      : 延迟执行Callable命令
    scheduleWithFixedRate, scheduleWithFixedDelay : 延迟并循环执行命令
  • 时间相关→TimeUtils.javaTest
    milliseconds2String                               : 将时间戳转为时间字符串
    string2Milliseconds                               : 将时间字符串转为时间戳
    string2Date                                       : 将时间字符串转为Date类型
    date2String                                       : 将Date类型转为时间字符串
    date2Milliseconds                                 : 将Date类型转为时间戳
    milliseconds2Date                                 : 将时间戳转为Date类型
    milliseconds2Unit                                 : 毫秒时间戳单位转换(单位:unit)
    getIntervalTime                                   : 获取两个时间差(单位:unit)
    getCurTimeMills, getCurTimeString, getCurTimeDate : 获取当前时间
    getIntervalByNow                                  : 获取与当前时间的差(单位:unit)
    isLeapYear                                        : 判断闰年
    getWeek, getWeekIndex                             : 获取星期
    getWeek, getWeekIndex                             : 获取星期
    getWeekOfMonth                                    : 获取月份中的第几周
    getWeekOfYear                                     : 获取年份中的第几周
  • 吐司相关→ToastUtils.java
    init               : 吐司初始化
    showShortToastSafe : 安全地显示短时吐司
    showLongToastSafe  : 安全地显示长时吐司
    showShortToast     : 显示短时吐司
    showLongToast      : 显示长时吐司
    cancelToast        : 取消吐司显示
  • 压缩相关→ZipUtils.javaTest
    zipFiles           : 批量压缩文件
    zipFile            : 压缩文件
    unzipFiles         : 批量解压文件
    unzipFile          : 解压文件
    unzipFileByKeyword : 解压带有关键字的文件
    getFilesPath       : 获取压缩文件中的文件路径链表
    getComments        : 获取压缩文件中的注释链表
    getEntries         : 获取压缩文件中的文件对象
  • 更新Log→update_log.md

做这份整理是想把它作为Android开发的小字典,当遇到一些琐碎问题时,不用再面向百度或者谷歌查询API的使用,费时费力,这里有的话,大家尽管撸走;同时也希望它能逐日壮大起来,期待大家的Star和完善,当然我也会一直更新发布版本和日志,为了方便大家导入,现已上传jcenter;其中很多代码也是汇四方之精华,谢谢前辈们的提供,当然最终还是要通过单元测试的,如有错误,请及时告之;开设QQ群提供讨论,群号:74721490,至于验证问题对大家来说肯定都是小case;最近在玩微博,玩的话向大家求个关注

Download


Gradle:

compile 'com.blankj:utilcode:1.3.0'

Proguard


-keep class com.blankj.utilcode.** { *; }
-keep classmembers class com.blankj.utilcode.** { *; }
-dontwarn com.blankj.utilcode.**

 

文/Blankj(简书作者)
原文链接:http://www.jianshu.com/p/72494773aace

AndroidStudio常用快捷键

作为一个Android开发者,最常使用的就是Android Studio了,我在这里声明Android Studio比Eclipse好用100倍,不服来辩。本文用于纪录Android Studio中相见恨晚的操作,阅读本文大概需要不确定时间。(你难道就不边读边试试?)我会用尽量简单明了的语言介绍。PS:多图,流量用户慎入。

更新日期 更新内容 备注
2016/9/22 更新Android Studio 2.2 查询示例程序的操作,具体见内容 5
2016/9/17 更新 提取 和 内联 的快捷操作,具体看内容 1.3.2 和 1.3.3 感谢MAIMIHO读者的提供。参考链接:12
2016/7/30 更新更简单的非空输入方法对象.nn
更新Windows版查看类的继承关系快捷键Ctrl+H 感谢3f76b4e62a13的补充
更新活动模版查看和自定义入口Preference->Editor->Live Templates 感谢Sacowiw的提供
2016/7/25 更新大纲 Windows版快捷键Ctrl+F12 感谢Alex_Cin,bryanno1的提供和验证

1 编写

1.1 活动模版

1.1.1 for循环原来可以这样

遍历集合的时候,对象.for就可以生成迭代循环遍历:

.fori可以这样:

.forr可以反向:

数字.for也可以:

1.1.2 判空可以这样

在写代码的时候,判空是不可避免的。判空可以这样,对象.null

非空可以这样,对象.notnull

非空还有更简单的方法,对象.nn

1.1.3 别再写if()了

if可是我们最常用的了,但是我劝你再也不要写if()了,试试任何可以判断的语句后面加上.if:

1.1.4 instance也可以很炫酷

1.1.5 活动模版自定义和查看入口

Preference->Editor->Live Templates,这个窗口下小伙伴们可以看到所有的活动模版,还可以自定义自己的活动模版。例如我就定义了一个tc,作为android:textColor=""的活动模版。

1.2 多行编辑

喜欢用sublime等编辑器的小伙伴对这个应该在熟悉不过了。

1.2.1 多行编辑

例如我们有四个Button要定义,可以先这样,按住alt键+鼠标左键一直向下拉,就可以选中多行,然后编辑就可以同时对多行进行编辑,编辑完相同部分再分别输入不同部分就ok了:

1.2.2 块编辑

比如我们要把上边定义的四个Button 改为TextView类型:

操作也是按住alt不放,拉对角线,拉出一块,就可以对选中的块,进行块编辑了。

1.3 快捷键

1.3.1 Alt+Enter

这个是Android Studio神快捷键。如果你还认为Alt+Enter键是导入包,那就大错特错了。以后有事没事就按下吧。它会根据不同的情况给出操作建议,大大提高工作效率。

eg.

我要获取布局文件中的RecyclerView,findViewById写好了,这个时候需要强制类型转化,在红线上按使用该快捷键,给出了提示Cast to …(此处省略好几个字),再回车,代码生成好了。

接下来是要给RecyclerView设置一个Adapter,那么我先写了没有的PersonAdapter类,那么这个类是没有的,提示红色,我们在该类上使用该快捷键,给出了提示:Create class …,回车,这个类便创建好了。

但是我们要实现RecyclerView.Adapter中的方法,我们在红线部分使用快捷键,看到给出提示implement method,回车,方法实现了。

Alt+Enter快捷键是Android Studio中的神键,它的功能远不止这些,没事就按一按吧。按按更健康。

1.3.2 提取 方法,style,layout等

我在写代码的时候都是先写可用的代码,把功能都实现之后,立即重构,在这个时候我经常用到 提取方法 的这个快捷键:alt+command+M

提取sytle,layout等并没有默认的快捷键。如果你的有,可能我们用的不是同一套,不过无论怎样,你都可以去偏好设置里去自定义快捷键。那么打开keymap。找到Extract,可以看到,包括之前的提取方法操作也在这里,下面的style和Layout就是提取样式和和布局了。你也可以看到还有很多。你可以根据自己的喜好了来自定义快捷键。

演示:

提取布局

提取样式

1.3.3 内联

对于上面我们提取出的方法,样式或者布局,这些都可以使用内联把他们加回使用的地方。这个我并不是很常用。不过还是介绍一下吧。这个默认快捷键是:alt+command+N,在keymap表中的Inline

将布局内联到当前布局

2 搜索

在写代码的过程中,代码检索永远都少不了。如果你是眼睛去找,那效率真的不知道要差到哪里去了。

2.1 搜索基本操作

这些搜索操作我叫做基本操作

操作 Mac Windows
搜索类 Command+O Ctrl+N
文件中搜索 Command+F Ctrl+F
搜索文件 Command+shift+O Ctrl+shift+N
全局查找 Command+shift+F Ctrl+shift+F

要是懒的话,这四个基本可以解决查找问题。

2.2 大纲

大纲快捷键 Mac:Command+F12 Windows:我不知道。。。(我自己用的Mac有些Windows的我也不知道。欢迎补充,PS:我的Mac开启了将Fx键用作标准功能键,如果没有开启的小伙伴,你的快捷键就是Command+Fn+F12),大纲出来了,就可以查看该类中的成员变量和成员方法,直接输入名称就可以筛选查询。

2.3 Search Everywhere

这个功能的强大就如它的名字一样,它的快捷键是双击shift,输入关键字就可以。就连窗口都可以搜索奥。

3 窗口

3.1 分屏

分屏可以上下,可以左右,我更喜欢左右分屏,有的时候很方便。

你可以直接使用Search Everywhere功能,然后输入split会有vertically和Horizontally两种,选择你要的就可以。或者在编辑窗口上的标签,右击,选择split vertically或者split Horizontally。我比较喜欢使用Search Everywhere,键盘总比鼠标快。

3.2 Hierarchy窗口

Hierarchy窗口可以让我们看清楚层级关系,还记得之前非常火的一个段子讲,是好朋友不会让你学Java的,然后附了一张Java继承关系的图,在继承关系层级很深,很复杂的时候,这个窗口简直不能太好。

这个是类的继承关系:

打开这个窗口,可以使用Search Everywhere功能,输入Hierarchy就可以,Mac也可以使用快捷键ctrl+H,Windows快捷键也是ctrl+H。

还有一个Call Hierarchy,可以显示出方法的调用层级关系:

这个的快捷键是ctrl+alt+H。

4 调试

调试过程在开发中也是少不了的。

4.1 快照

有关UI的编程,这个功能知道会省很多事。

在运行过程中,可以给手机截图,并保存。再也不用手机截图然后再传电脑了。

4.2 录屏

在做有关动画的功能的时候,录屏功能可以让你更好的检查动画是否正确。

4.3 断点

断点的使用,断点的用法不止是让程序停下来。试一试在停下来之后使用快捷键Alt+F8,调出Evaluate Expression界面,在该界面你可以输入你想查看的值,就可以显示出来。

除此之外在断点处右击,会出现如下的界面,你可以在图中光标处输入断点停下的条件,当你需要在一个循环中打断点的时候,这简直就是神技:

在上图中Suspend前的勾取消会看到这样的界面:

这个界面上内容更多,比如你选中了Log evaluated expression,然后在下面的输入框中输入你想要输出的log,那么这个断点就不会在这里停下来,而是在控制台输出一条日志。

5 查询示例程序

这个功能让我感觉越来越像代码的搬运工了! 使用该内容需要,Android Studio2.2以及在SDK Manager中下载Samples for SDK,然后重启AS,再然后尽人事听天命,昨天搞了半天就是出不来,不知道今天怎么好了……究竟是AS的灵异事件还是我的努力感动了上天,反正我成功了。

在一个不会用的类上右键,选择Find Sample Code,或者使用你看到的快捷键alt+F8,Windows版的快捷键自己查询。之后就可以方便的查看示例代码。例如我们查看ColorMatrix的示例代码:

查询结果会在下方出现,不过有的时候要等很久,有的还找不到:

不过已经非常不错了。首先有Android官方网站的官方文档。下面会有几个包涵ColorMatrix的栗子。单击可以在右边直接查看其内容。如果硬是出不了的话,又实在想看,那么就去github上去查看吧,有一个组织叫GoogleSample,去搜就行了。

结束语

这篇文章没有结束,正在看的你如果对Android Studio还有其他的相见恨晚的操作,欢迎留言补充。希望这篇文章对大家有帮助。

[Android] 不通过usb调试,使用网络

当手机需要充电或usb口被其他占用时,可以通过设置网络来进行连接电脑调试,前提是手机和电脑已经联网。

  1. 首先手机通过usb连接电脑
  2. 在命令行输入:adb tcpip 5678(5678为端口号,可随意指定)
  3. 断开usb数据线连接
  4. 在命令行输入:adb connect <手机IP地址>:5678
  5. 然后就可以在电脑端使用adb命令操作手机了,例如adb install apk等,由于通过网络传输,速度没有直接连接usb快。
  6. 如果要恢复usb,使用命令:adb usb即可。

注意:手机IP可以在手机的“设置”->”关于手机”->“状态信息”里查看,不同手机路径稍微有差别。

这个方法在实际使用中有时会慢,根据当前网络情况会有很大差别。所以比较稳定的办法还是通过usb调试吧。