1.模拟返回按键(返回的比较慢)
try {
Runtime.getRuntime().exec("input keyevent " + KeyEvent.KEYCODE_BACK);
} catch (IOException e) {
e.printStackTrace();
}
2.检测当前网络状态
/**
* 检测当前网络状态
* @param context
* @return
*/
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo info = connectivity.getActiveNetworkInfo();
if (info != null && info.isConnected()) {
// 当前网络是连接的
if (info.getState() == NetworkInfo.State.CONNECTED) {
// 当前所连接的网络可用
return true;
}
}
}
return false;
}
3.复制文本
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData mClipData = ClipData.newPlainText("Label", "要复制的文字");
cm.setPrimaryClip(mClipData);
4.设置字体不随系统字体更改
@Override
public Resources getResources() {
Resources res = super.getResources();
Configuration config = new Configuration();
config.setToDefaults();
res.updateConfiguration(config, res.getDisplayMetrics());
return res;
}
5.Activity重载自己可用于无网络页面重新加载(注意:不能是最后一个Activity不然会有动画)
startActivity(new Intent(Main2Activity.this, Main2Activity.class));
overridePendingTransition(0, 0);
finish();
6.BuildConfig类
参考自:http://blog.csdn.net/lvxiangan/article/details/71601451
BuildConfig类是一个根据build.gradle配置文件自动生成的类,有点类似于R.class,生成后不能修改
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "com.sign.demo";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
}
可用BUILD_TYPE属性进行版本查看、DEBUG属性日志控制等
BUILD_TYPE debug(测试包) release(正式包)
DEBUG true (测试包) false(正式包)可用此属性管理日志数据
7.MessageFormat格式化字符串
参考自:http://www.cnblogs.com/fjdingsd/p/5143625.html
这里只使用了最简单的占位符的使用方法:
public class MainActivity extends AppCompatActivity {
int max = 100;
int now = 0;
private TextView tvContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvContent = findViewById(R.id.tv_content);
final String format = "照片上传中... {0}/{1}";
new Timer().schedule(new TimerTask() {
@Override
public void run() {
now++;
if (now < max) {
runOnUiThread(new Runnable() {
@Override
public void run() {
//now max会替换掉{}中的0,1
tvContent.setText(MessageFormat.format(format, now, max));
}
});
}
}
}, 0, 2000);
}
}
8.android 热启动 冷启动
参考自:https://www.cnblogs.com/xunzhi/p/5794793.html
- 冷启动:当启动应用时,后台没有该应用的进程,系统会重新创建一个新的进程分配给该应用。因为系统会重新创建一个新的进程分配给该应用,所以会先创建和初始化application类,再创建和初始化MainActivity类(包括一系列的测量、布局、绘制)最后显示到界面上
- 热启动:当启动应用时,后台已有应用的进程(例如:按back键、home键应用虽然会退出,但是该应用的进程依然保留在后台,可通过任务列表查看)。因为热启动是从已有的进程中启动,所以不会重新创建和初始化application,而只是重新创建和初始化MainActivity(测量、布局、绘制)
因为一个应用从进程的创建到销毁,application只会初始化一次
9.去掉ScrollView、RecyclerView、ViewPager等可滑动控件,滑动到边缘的光晕效果
android:overScrollMode="never"
10.android:descendantFocusability
项目中RecyclerView条目中包含EditText时,由于EditText自动抢占焦点导致自动滚动的问题
给RecyclerView设置 android:descendantFocusability="beforeDescendants"
此属性作用为:定义此ViewGroup与子视图的焦点归属
此属性的值有三种:
beforeDescendants
viewgroup会优先其子类控件而获取到焦点afterDescendants
viewgroup只有当其子类控件不需要获取焦点时才获取焦点blocksDescendants
viewgroup会覆盖子类控件而直接获得焦点
recyclerview包含WebView时,点击WebView会滑动到顶部,刷新数据时也会抢占焦点
recyclerview设置:android:descendantFocusability="blocksDescendants"
11.view.getLocationInWindow(int[])
获得当前view在窗口中的坐标
传入的参数int[] leftTop = {0 , 0}
调用后leftTop[0]为在窗口中left坐标
leftTop[1]为在窗口中top坐标
区分view.getLeft() view.getTop是针对于父视图的相对位置
判断点击的位置是否在某view中
public boolean isInBottomLayout(MotionEvent event) {
if (bottom_layout != null) {
int[] leftTop = {0, 0};
//获取bottom_layout当前的location位置
bottom_layout.getLocationInWindow(leftTop);
int left = leftTop[0];
int top = leftTop[1];
int bottom = top + bottom_layout.getHeight();
int right = left + bottom_layout.getWidth();
if (event.getX() > left && event.getX() < right
&& event.getY() > top && event.getY() < bottom) {
// 点击在bottomlayout内,保留事件
return false;
} else {
return true;
}
}
return false;
}
12.优化点击应用图标响应速度
https://blog.csdn.net/old_land/article/details/79708179?utm_source=blogxgwz8
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@drawable/welcome_pic</item>
<item name="android:windowFullscreen">true</item>
13.从全屏页面(见12条设置)跳转到非全屏页面,由于状态栏由不可见到可见,引起很明显的界面下移
参考:https://www.jianshu.com/p/63bba2e09b78
效果可以看:https://blog.csdn.net/u013011318/article/details/48296869
他的判断感觉写反了,而且不太好用if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
我的做法是
- 在启动页的setcontentview方法之前,设置透明状态栏(因为启动页是全屏,状态栏不会显示)
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
//透明状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window window = getWindow();
window.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
- 在跳转到应用主页之前,切换到非全屏状态,状态栏会显示出来,但因为是透明状态栏,布局会拓展到系统栏的后面,跳转时只是把状态栏显示出来,并不会让布局发生下移
透明状态栏,布局会拓展到系统栏的后面:https://blog.csdn.net/QQxiaoqiang1573/article/details/79888186
this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
或者
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
14.allowBackup属性
manifest中application节点allowBackup
属性默认为true,允许通过adb backup对打开USB调试的设备进行数据备份,但会引起信息泄漏问题,详见 https://blog.csdn.net/yanbober/article/details/46417531
15.关于android LayoutInflater加载view的几个方法
参考:https://www.jb51.net/article/82620.htm
inflate(layoutId,null)–>调用inflate(layoutId,null,false) 返回子view,无param
inflate(layoutId,parent)–>调用inflate(layoutId,parent,true) 同最后一个,返回parent,子view被添加到parent中,携带param
inflate(layoutId,null,true/false) 返回子view,无param
inflate(layoutId,parent,false) 返回子view,携带param
inflate(layoutId,parent,true) 返回parent,子view被添加到parent中,携带param
代码如下:
LayoutInflater layoutInflater = LayoutInflater.from(this);
LinearLayout llMain = findViewById(R.id.ll_main);
View view1 = layoutInflater.inflate(R.layout.button, null);
View view2 = layoutInflater.inflate(R.layout.button, llMain);
View view3 = layoutInflater.inflate(R.layout.button, null, false);
View view4 = layoutInflater.inflate(R.layout.button, null, true);
View view5 = layoutInflater.inflate(R.layout.button, llMain, false);
View view6 = layoutInflater.inflate(R.layout.button, llMain, true);
/**
*结果:
* view1 button null null
* view2 llMain FrameLayout.param FrameLayout (== view6)
* view3 button null null
* view4 button null null
* view5 button LinearLayout.param null
* view6 llMain FrameLayout.param button
*/
Log.d(TAG, "view1 = " + view1 + "view1 layoutParams = " + view1.getLayoutParams() + "view.getParent = " + view1.getParent());
Log.d(TAG, "view2 = " + view2 + "view2 layoutParams = " + view2.getLayoutParams() + "view.getParent = " + view2.getParent());
Log.d(TAG, "view3 = " + view3 + "view3 layoutParams = " + view3.getLayoutParams() + "view.getParent = " + view3.getParent());
Log.d(TAG, "view4 = " + view4 + "view4 layoutParams = " + view4.getLayoutParams() + "view.getParent = " + view4.getParent());
Log.d(TAG, "view5 = " + view5 + "view5 layoutParams = " + view5.getLayoutParams() + "view.getParent = " + view5.getParent());
Log.d(TAG, "view6 = " + view6 + "view6 layoutParams = " + view6.getLayoutParams() + "view.getChildAt(0) = " + ((ViewGroup) view6).getChildAt(0));
日志:
view1 = android.support.v7.widget.AppCompatButton{4268d70 VFED..C.. ......I. 0,0-0,0}view1 layoutParams = nullview.getParent = null
view2 = android.widget.LinearLayout{82288e9 V.E...... ......I. 0,0-0,0 #7f07004e app:id/ll_main}view2 layoutParams = android.widget.FrameLayout$LayoutParams@9a1796eview.getParent = android.support.v7.widget.ContentFrameLayout{5d4680f V.E...... ......I. 0,0-0,0 #1020002 android:id/content}
view3 = android.support.v7.widget.AppCompatButton{dbf109c VFED..C.. ......I. 0,0-0,0}view3 layoutParams = nullview.getParent = null
view4 = android.support.v7.widget.AppCompatButton{611caa5 VFED..C.. ......I. 0,0-0,0}view4 layoutParams = nullview.getParent = null
view5 = android.support.v7.widget.AppCompatButton{1efbe7a VFED..C.. ......I. 0,0-0,0}view5 layoutParams = android.widget.LinearLayout$LayoutParams@b79762bview.getParent = null
view6 = android.widget.LinearLayout{82288e9 V.E...... ......I. 0,0-0,0 #7f07004e app:id/ll_main}view6 layoutParams = android.widget.FrameLayout$LayoutParams@9a1796eview.getChildAt(0) = android.support.v7.widget.AppCompatButton{4fa9a88 VFED..C.. ......I. 0,0-0,0}
16.java格式化double数据 千分符和小数点互换(千分符是’.’ 小数点是’,’)
DecimalFormatSymbols decimalSymbols = DecimalFormatSymbols.getInstance();
decimalSymbols.setDecimalSeparator(',');
decimalSymbols.setGroupingSeparator('.');
DecimalFormat df = new DecimalFormat("###,###.00",
decimalSymbols);
String format = df.format(2999999999999.115);
==>
2.999.999.999.999,12
17.shouldOverrideUrlLoading(WebView view, WebResourceRequest request)未拦截到请求
shouldOverrideUrlLoading(WebView view, String url)方法在7.0之后被废弃
shouldOverrideUrlLoading(WebView view, WebResourceRequest request)方法则是在7.0之后添加的
所以我们想要拦截某个请求时就需要重写这两个方法,之前没太注意这里,只重写了shouldOverrideUrlLoading(WebView view, WebResourceRequest request)方法,导致6.0的请求未被拦截。
https://stackoverflow.com/questions/36484074/is-shouldoverrideurlloading-really-deprecated-what-can-i-use-instead
18.改变阴影的深浅度
给控件添加阴影的方法一般是改变控件的elevation属性,直接设置的阴影设计觉得有点重。。。
改后的效果如下:
代码:
两个控件xml中属性一致,不过在代码中对阴影的透明度做了修改
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:background="@drawable/shape_solid_white_radius_10"
android:elevation="3dp"
android:padding="20dp"
android:text="测试" />
<TextView
android:id="@+id/tv_light"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:background="@drawable/shape_solid_white_radius_10"
android:elevation="3dp"
android:padding="20dp"
android:text="测试" />
ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), ScreenUtils.dp2px(MainActivity.this, 10));
outline.setAlpha(0.5f);
}
};
findViewById(R.id.tv_light).setOutlineProvider(viewOutlineProvider);
19.改变drawable颜色
给现有的资源文件改变颜色,就不用重新切图了
慎用 这种方式好像会把所有引用到此文件的颜色都改变 没办法一个地方黑色 一个地方红色 改了就会全改掉
Drawable arrowDrawable = DrawableCompat.wrap(getResources().getDrawable(R.drawable.ic_arrow_black));
DrawableCompat.setTintList(arrowDrawable, getResources().getColorStateList(R.color.gray));
imageView.setImageDrawable(arrowDrawable);