-
下载git
brew install git
-
adb命令查看运行APP当前页面的Activity名称
adb shell dumpsys activity activities | grep mResumedActivity 或者 adb shell dumpsys window | grep mCurrentFocus
-
declare-styleable是给自定义控件添加自定义属性用的。
-
TypedArray typedArray = context.obtainStyledAttributes()
获取在style中定义的各种属性值。使用完之后,需要调用recycle方法将typeArray回收 typedArray.recycle();
-
Consumer接口
Consumer 接口中的抽象方法 void accept(T t),意为消费一个指定泛型的数据, 其数据类型由泛型决定。 -
Schedulers.from(Executor) 方法将一个 Executor 转换成一个新的 Scheduler 实例。
-
TabLayout属性app:tabMode 表示此TabLayout中当子view超出屏幕边界时候,将提供滑动以便滑出不可见的那些子view。
-
BottomSheetBehavior.setDraggable(false); 以防止拖动工作表折叠和展开
-
ViewStub 是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有 ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。
-
view.getTop()是View顶部距离父容器顶部的距离
view.getBottom()却是View底部距离父容器顶部的距离
-
Rxjava 学习链接
-
subscribeOn()指定被观察者的线程,要注意的是,如果多次调用此方法,只有第一次有效。
observeOn() 指定观察者的线程,每指定一次就会生效一次。
-
查看栈信息
adb shell dumpsys activity activities
查看一个包名中当前所存在的进程信息
adb shell ps | grep com.bing.Day1
-
TouchSlop 是系统所能识别出的被认为是滑动的最小距离,如果两次滑动之间的距离小于这个常量,那么系统就不认为你是在进行滑动操作。这是一个常量,和设备有关,在不同设备上这个值可能是不同的,通过如下方式获取到这个常量
ViewConfiguration.get(context).getScaledTouchSlop();
-
scrollTo()和scrollBy()的区别
scrollTo()方法是让View相对于初始的位置滚动某段距离,由于View的初始位置是不变的,因此不管我们scrollTo多少次滚动到的都将是同一个位置。而scrollBy()方法则是让View相对于当前的位置滚动某段距离,那每当我们scrollBy一次,View的当前位置都进行了变动。 -
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
当这个window对用户是可见状态,则保持设备屏幕不关闭且不变暗
-
MotionEvent的getX()和getRawX()的区别
x,y是相对于该控件本身左上点的相对位置。
而rawx,rawy始终是相对于屏幕左上点的位置。 -
添加系统级别的window
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
initWindow();
}
});
}
private void initWindow() {
//6.0以上需要用户手动打开权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
//打开设置页,让用户打开设置
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + MainActivity.this.getPackageName()));
startActivityForResult(intent, 1);
} else {
//已经打开了权限
addWindow();
}
} else {
//6.0以下直接 Manifest申请该权限就行
addWindow();
}
}
private void addWindow() {
Button window = new Button(this);
window.setText("我是window");
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0, PixelFormat.TRANSPARENT);
// flag 设置 Window 属性
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
// type 设置 Window 层级:TYPE_ACCESSIBILITY_OVERLAY 系统级别window
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
layoutParams.x = 100;
layoutParams.y = 300;
WindowManager windowManager = getWindowManager();
windowManager.addView(window, layoutParams);
window.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
layoutParams.x = rawX;
layoutParams.y = rawY;
windowManager.updateViewLayout(window, layoutParams);
break;
default:
break;
}
return false;
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.canDrawOverlays(this)) {
addWindow();
} else {
Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
}
}
break;
default:
break;
}
}
}
-
自定义Camera:TextureView + Camera 学习链接
-
ViewConfiguration.get(getContext()).getScaledTouchSlop());
系统滑动距离的最小值,大于该值可以认为滑动