- onLongClick() 返回true时会自动震动
getLocationInWindow 不算notification bar
getLocationOnScreen 整个屏幕
3.
fillBefore是指动画结束时画面停留在此动画的第一帧; 默认值为true
fillAfter是指动画结束是画面停留在此动画的最后一帧。默认值为false
1,FillEnable = false 时,FillBefore 和FillAfter的值将被忽略,此时FillEnable=Flase时和FillBefore =true且FillAfter=true,且FillEnabled=true等价,也就是开始结束都会被fill坑爹。。。
2,FillEnable = true时,FillBefore = true,FillAfter = false
只在第一帧fill
3,FillEnable = true时,FillBefore = false,FillAfter=true
只在最后一帧fill
4,FillEnable = true时,FillBefore = false,FillAfter=false
这个控制也比较坑爹,从变量名理解以为只要FillEnable=false就好,其它当FillEnable=false时又回到第1种情况太坑爹了。。
4、
在Manifest中的Activity里添加:android:windowSoftInputMode="adjustResize"
可以使得键盘输入时布局重新变化。
5、
测量显示区域,windowRect为去掉statusBar 和输入法的区域
Rect windowRect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(windowRect);
- ListView.getChildAt(int)
child是指所有可见的item(包括部分可见的,以及header和footer,可通过getHeaderCount来获取数量)
- 点击返回按钮,调用顺序,在任何一处调用都可以拦截点击事件。
在dispatchKeyEvent()中返回true,可以拦截点击事件,但仍然会被调用两次,另外两个函数不会被调用;
在onKeyDown()中返回true,仍按以下顺序,但不会调用onBackPressed();
在onBackPressed()中返回true,仍按以下顺序,拦截点击事件。
dispatchKeyEvent() event.getKeyCode() = true
onKeyDown() keyCode = true, event.getRepeatCount() = 0
dispatchKeyEvent() event.getKeyCode() = true
onBackPressed()
8、MotionEvent
http://stackoverflow.com/questions/15467255/getdowntime-and-geteventtime
event.getDownTime() 返回的是一系列事件发生时,第一次事件的事件(比如ACTION_DOWN)
evnet.getEventTime() 返回的是当前事件发生的时间,也是一些列事件的最后一次事件的时间(比如ACITON_UP)
9、
重写dispatchKeyEventPreIme()可以在输入法之前拦截按键事件,尤其是back键
dispatchKeyEventPreIme()
10、各种scroll
scrollBy(int x, int y) x,y为两个方向上移动的距离,scroll之后会留下空白区域;
smoothScrollBy(int dis, int duration) dis为移动距离,duration为移动距离的时间(毫秒),但如果设置时间不当,会导致移动距离未完成就结束scroll;
smoothScrollByOffset(int offset) offset不是移动的距离,而是listview中的具体position
smoothScrollToPositionFromTop(int postion, int offset) position为list中的具体一项,offset为指定项的位置在window左上角时,移动的距离;
11、popupwindow setTouchInterceptor(new View.OnTouchListener()...)
可以拦截touch事件,popupwindow会拦截到ACTION_OUTSIDE事件。
12、
int containerViewId = getResources().getIdentifier("content", "android.R.id", getPackageName());
int containerViewId = getResources().getIdentifier("rootView", "id", getPackageName());
13、Drawable
layer-list 设置drawable的层次结构
level-list 设置drawable的状态,可以通过setDrawableLevel来改变状态以显示不同的效果
14、改变window的进出场动画
getWindow().setWindowAnimations(R.style.BMBWindowSlideInOutFromRight);
15、改变View的层次,可以在动画显示时将View添加到层次较高的layer,防止Transition动画的遮挡。
ViewGroup viewGroup = (ViewGroup)getWindow().getDecorView();
viewGroup.getOverlay().add(btnDice);
viewGroup.getOverlay().add(btnSend);
16、监听ACTION_DOWN, ACTION_UP事件并播放动画时,可以考虑使用handler来保证动画的播放,并防止UI线程被阻塞。尤其是在onTouchEvent()中,不适合做耗时过长的动作,否则会使得后面的Touch事件无法被捕捉到
17、onMeasure()方法
MeasureSpec.EXACTLY:match_parent , accurate
MeasureSpec.AT_MOST:wrap_content
计算完之后需要调用以下方法才能生效:
setMeasuredDimension(mWidth, mHeight);
18、解决scrollview和listview的冲突问题,可以重写onMeasure:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
/**
* 解决ScrollView与ListView的嵌套问题
*/
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
19、配置发生变化时,保持大量数据时比较耗时,可以考虑使用fragment
在运行时配置发生变化时,在Fragment中保存有状态的对象,并提供相应的getter和setter方法,在activity中调用用于get和set。(Fragment可以没有UI,仅作为保存对象使用)
a) 继承Fragment,声明引用指向你的有状态的对象
b) 当Fragment创建时调用setRetainInstance(boolean)
c) 把Fragment实例添加到Activity中
d) 当Activity重新启动后,使用FragmentManager对Fragment进行恢复
不使用onSaveIntanceState()的原因:
如果重新启动你的Activity需要恢复大量的数据,重新建立网络连接,或者执行其他的密集型操作,这样因为配置发生变化而完全重新启动可能会是一个慢的用户体验。并且,使用系统提供的onSaveIntanceState()的回调中,使用Bundle来完全恢复你Activity的状态是可能是不现实的(Bundle不是设计用来携带大量数据的(例如bitmap),并且Bundle中的数据必须能够被序列化和反序列化),这样会消耗大量的内存和导致配置变化缓慢。在这样的情况下,当你的Activity因为配置发生改变而重启,你可以通过保持一个Fragment来缓解重新启动带来的负担。这个Fragment可以包含你想要保持的有状态的对象的引用。
20、fragment声明周期
与activity声明周期比较
场景演示 : 切换到该Fragment
11-29 14:26:35.095: D/AppListFragment(7649): onAttach
11-29 14:26:35.095: D/AppListFragment(7649): onCreate
11-29 14:26:35.095: D/AppListFragment(7649): onCreateView
11-29 14:26:35.100: D/AppListFragment(7649): onActivityCreated
11-29 14:26:35.120: D/AppListFragment(7649): onStart
11-29 14:26:35.120: D/AppListFragment(7649): onResume
屏幕灭掉:
11-29 14:27:35.185: D/AppListFragment(7649): onPause
11-29 14:27:35.205: D/AppListFragment(7649): onSaveInstanceState
11-29 14:27:35.205: D/AppListFragment(7649): onStop
屏幕解锁
11-29 14:33:13.240: D/AppListFragment(7649): onStart
11-29 14:33:13.275: D/AppListFragment(7649): onResume
切换到其他Fragment:
11-29 14:33:33.655: D/AppListFragment(7649): onPause
11-29 14:33:33.655: D/AppListFragment(7649): onStop
11-29 14:33:33.660: D/AppListFragment(7649): onDestroyView
切换回本身的Fragment:
11-29 14:33:55.820: D/AppListFragment(7649): onCreateView
11-29 14:33:55.825: D/AppListFragment(7649): onActivityCreated
11-29 14:33:55.825: D/AppListFragment(7649): onStart
11-29 14:33:55.825: D/AppListFragment(7649): onResume
回到桌面
11-29 14:34:26.590: D/AppListFragment(7649): onPause
11-29 14:34:26.880: D/AppListFragment(7649): onSaveInstanceState
11-29 14:34:26.880: D/AppListFragment(7649): onStop
回到应用
11-29 14:36:51.940: D/AppListFragment(7649): onStart
11-29 14:36:51.940: D/AppListFragment(7649): onResume
退出应用
11-29 14:37:03.020: D/AppListFragment(7649): onPause
11-29 14:37:03.155: D/AppListFragment(7649): onStop
11-29 14:37:03.155: D/AppListFragment(7649): onDestroyView
11-29 14:37:03.165: D/AppListFragment(7649): onDestroy
11-29 14:37:03.165: D/AppListFragment(7649): onDetach
21、配置发生变化,在menifest中进行属性设置,并在activity中自行对config的变化做适配(在onConfigChanged()方法中),就可以防止activity重建。
22、自定义Dialog,显示在底部
必须卸载onCreate里,利用window使其显示在屏幕下方,并且宽度占满屏幕。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_complex_condition_picker);
ButterKnife.bind(this);
Window window = getWindow();
WindowManager.LayoutParams wlp = window.getAttributes();
wlp.gravity = Gravity.BOTTOM;
wlp.width = WindowManager.LayoutParams.MATCH_PARENT;
wlp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(wlp);
initViews();
}
自定义的style
<style name="ComplexConditionPickerDialog">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowIsTranslucent">false</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowCloseOnTouchOutside">true</item>
<!--<item name="android:windowAnimationStyle">@style/AnimRewardDialog</item>-->
</style>
23、解决Listview和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);
}
24、EditText获得焦点时自动弹出软键盘的解决方法
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
}
});
25、Window和Display测试
private void testDisplay(String from){
BMBLogUtils.d(Config.LOGTAG, " ======= TestDisplay "+from+"=======");
Window window = getWindow();
Display display = window.getWindowManager().getDefaultDisplay();
View decorView = window.getDecorView();
BMBLogUtils.d(Config.LOGTAG, " TestDisplay window = "+(window == null ? "null":window)
+", display = "+(display == null ? "null" : display)+", decorView = "+(decorView == null ? "null" : decorView));
//1
Point outPoint = new Point();
display.getSize(outPoint);
BMBLogUtils.d(Config.LOGTAG, "1. TestDisplay display.getSize(outPoint), outPoint = "+outPoint.toString());
//2
Point realSize = new Point();
display.getRealSize(realSize);//API level 17
BMBLogUtils.d(Config.LOGTAG, "2. TestDisplay display.getRealSize(realSize), realSize = " + realSize.toString());
//3
Point smallPoint = new Point();
Point largePoint = new Point();
display.getCurrentSizeRange(smallPoint, largePoint);
BMBLogUtils.d(Config.LOGTAG, "3. TestDisplay display.getCurrentSizeRange(smallPoint, largePoint), smallPoint = "
+ smallPoint.toString() + ", largePoint = " + largePoint.toString());
//4
Rect rectSize = new Rect();
display.getRectSize(rectSize);
BMBLogUtils.d(Config.LOGTAG, "4. TestDisplay display.getRectSize(rectSize), rectSize = " + rectSize.toString());
//5
DisplayMetrics displayMatrix = new DisplayMetrics();
display.getMetrics(displayMatrix);
BMBLogUtils.d(Config.LOGTAG, "5. TestDisplay display.getMetrics(displayMatrix), displayMatrix = " + displayMatrix.toString());
//6
DisplayMetrics realDisplayMatrix = new DisplayMetrics();
display.getRealMetrics(realDisplayMatrix);//API level 17
BMBLogUtils.d(Config.LOGTAG, "6. TestDisplay display.getRealMetrics(realDisplayMatrix), realDisplayMatrix = " + realDisplayMatrix.toString());
//7
WindowManager.LayoutParams windowParams = window.getAttributes();
BMBLogUtils.d(Config.LOGTAG, "7. TestDisplay windowParams = window.getAttributes(), windowParams = " + windowParams.toString());
//8
ViewGroup.LayoutParams decorViewParams = decorView.getLayoutParams();
if(decorViewParams == null){
BMBLogUtils.d(Config.LOGTAG, "8. TestDisplay decorViewParams = decorView.getLayoutParams(), decorViewParams = "+"null");
}else{
BMBLogUtils.d(Config.LOGTAG, "8. TestDisplay decorViewParams = decorView.getLayoutParams(), decorViewParams = VG.LayoutParams{height = " + decorViewParams.height + ", width = " + decorViewParams.width + "}");
}
//9
Rect visibleFrameRect = new Rect();
decorView.getWindowVisibleDisplayFrame(visibleFrameRect);
BMBLogUtils.d(Config.LOGTAG, "9. TestDisplay visibleFrameRect = decorView.getWindowVisibleDisplayFrame(visibleFrameRect), visibleFrameRect = " + visibleFrameRect.toString());
BMBLogUtils.d(Config.LOGTAG, " ======================= END ======================");
}
D/XIANZHEZLOGTAG(20345): ======= TestDisplay onCreate()=======
D/XIANZHEZLOGTAG(20345): TestDisplay window = com.android.internal.policy.impl.PhoneWindow@42b0e868, display = Display id 0: DisplayInfo{"内置屏幕", app 1080 x 1920, real 1080 x 1920, largest app 1794 x 1845, smallest app 1080 x 1005, 60.0 fps, rotation0, density 480 (442.451 x 443.345) dpi, layerStack 0, type BUILT_IN, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}, DisplayMetrics{density=3.0, width=1080, height=1920, scaledDensity=3.0, xdpi=442.451, ydpi=443.345}, isValid=true, decorView = com.android.internal.policy.impl.PhoneWindow$DecorView{42b495a0 V.E..... R.....ID 0,0-0,0}
D/XIANZHEZLOGTAG(20345): 1. TestDisplay display.getSize(outPoint), outPoint = Point(1080, 1920)
D/XIANZHEZLOGTAG(20345): 2. TestDisplay display.getRealSize(realSize), realSize = Point(1080, 1920)
D/XIANZHEZLOGTAG(20345): 3. TestDisplay display.getCurrentSizeRange(smallPoint, largePoint), smallPoint = Point(1080, 1005), largePoint = Point(1794, 1845)
D/XIANZHEZLOGTAG(20345): 4. TestDisplay display.getRectSize(rectSize), rectSize = Rect(0, 0 - 1080, 1920)
D/XIANZHEZLOGTAG(20345): 5. TestDisplay display.getMetrics(displayMatrix), displayMatrix = DisplayMetrics{density=3.0, width=1080, height=1920, scaledDensity=3.0, xdpi=442.451, ydpi=443.345}
D/XIANZHEZLOGTAG(20345): 6. TestDisplay display.getRealMetrics(realDisplayMatrix), realDisplayMatrix = DisplayMetrics{density=3.0, width=1080, height=1920, scaledDensity=3.0, xdpi=442.451, ydpi=443.345}
D/XIANZHEZLOGTAG(20345): 7. TestDisplay windowParams = window.getAttributes(), windowParams = WM.LayoutParams{(0,0)(fillxfill) ty=2 fl=#810100 pfl=0x8 wanim=0x10302a1 meizuFlags=0x1 imeOffset=-1 splitActionBarHeight=0Meizu WM.LayoutParams [ flags=0x0] }
D/XIANZHEZLOGTAG(20345): 8. TestDisplay decorViewParams = decorView.getLayoutParams(), decorViewParams = null
D/XIANZHEZLOGTAG(20345): 9. TestDisplay visibleFrameRect = decorView.getWindowVisibleDisplayFrame(visibleFrameRect), visibleFrameRect = Rect(0, 0 - 1080, 1920)
D/XIANZHEZLOGTAG(20345): ======================= END ======================
D/XIANZHEZLOGTAG(20345): ======= TestDisplay onWindowFocusChanged=======
D/XIANZHEZLOGTAG(20345): TestDisplay window = com.android.internal.policy.impl.PhoneWindow@42b0e868, display = Display id 0: DisplayInfo{"内置屏幕", app 1080 x 1920, real 1080 x 1920, largest app 1794 x 1845, smallest app 1080 x 1005, 60.0 fps, rotation0, density 480 (442.451 x 443.345) dpi, layerStack 0, type BUILT_IN, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}, DisplayMetrics{density=3.0, width=1080, height=1920, scaledDensity=3.0, xdpi=442.451, ydpi=443.345}, isValid=true, decorView = com.android.internal.policy.impl.PhoneWindow$DecorView{42b495a0 V.E..... R.....ID 0,0-1080,1776}
D/XIANZHEZLOGTAG(20345): 1. TestDisplay display.getSize(outPoint), outPoint = Point(1080, 1920)
D/XIANZHEZLOGTAG(20345): 2. TestDisplay display.getRealSize(realSize), realSize = Point(1080, 1920)
D/XIANZHEZLOGTAG(20345): 3. TestDisplay display.getCurrentSizeRange(smallPoint, largePoint), smallPoint = Point(1080, 1005), largePoint = Point(1794, 1845)
D/XIANZHEZLOGTAG(20345): 4. TestDisplay display.getRectSize(rectSize), rectSize = Rect(0, 0 - 1080, 1920)
D/XIANZHEZLOGTAG(20345): 5. TestDisplay display.getMetrics(displayMatrix), displayMatrix = DisplayMetrics{density=3.0, width=1080, height=1920, scaledDensity=3.0, xdpi=442.451, ydpi=443.345}
D/XIANZHEZLOGTAG(20345): 6. TestDisplay display.getRealMetrics(realDisplayMatrix), realDisplayMatrix = DisplayMetrics{density=3.0, width=1080, height=1920, scaledDensity=3.0, xdpi=442.451, ydpi=443.345}
D/XIANZHEZLOGTAG(20345): 7. TestDisplay windowParams = window.getAttributes(), windowParams = WM.LayoutParams{(0,0)(fillxfill) sim=#100 ty=1 fl=#1810100 pfl=0x8 wanim=0x10302a1 meizuFlags=0x1 imeOffset=-1 splitActionBarHeight=0Meizu WM.LayoutParams [ flags=0x0] }
D/XIANZHEZLOGTAG(20345): 8. TestDisplay decorViewParams = decorView.getLayoutParams(), decorViewParams = VG.LayoutParams{height = -1, width = -1}
D/XIANZHEZLOGTAG(20345): 9. TestDisplay visibleFrameRect = decorView.getWindowVisibleDisplayFrame(visibleFrameRect), visibleFrameRect = Rect(0, 75 - 1080, 1776)
D/XIANZHEZLOGTAG(20345): ======================= END ======================
26、hashCode()和equals()的关系
hashCode()的返回值和equals()的关系如下:
•如果x.equals(y)返回“true”,那么x和y的hashCode()必须相等。
•如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。
equals()先要查null和是否是同一类型。查同一类型是为了避免出现ClassCastException这样的异常给丢出来。查 null是为了避免出现NullPointerException这样的异常给丢出来。
27、layout animation
分为5种
LayoutTransition.APPEARING
LayoutTransition.DISAPPEARING
LayoutTransition.CHANGING
LayoutTransition.CHANGE_APPEARING
LayoutTransition.CHANGE_DISAPPEARING
有些种类会有默认的动画,一旦使能layout animation会默认出现,如果不想出现默认的效果,需要手动设为null,如:
lt.setAnimator(LayoutTransition.CHANGE_APPEARING, null);
28、measure()
在UI未渲染出来之前是无法直接getHeight(), getWidth()来获取高宽的,需要先measure(),然后getMeasuredHeight(), getMeasuredWidth()来获取高宽。在measure时的MeasureSpec很重要,应配合view的布局参数选择适当的Mode。
可用于测量wrap_content的:
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
29、activity start时显示键盘,只需要在Manifest里为该Activity添加以下属性
android:windowSoftInputMode="stateVisible"
30、获得activity content view:
findViewById(android.R.id.content)
31、当ImageView中加载图片与实际图片大小或者比例不一致时,应考虑使用以下属性来做适配:
android:adjustViewBounds="true"
32、隐藏status bar,完全不显示:
You can do it programatically:
public class ActivityName extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// remove title
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
}
}
Or you can do it via your AndroidManifest.xml file:
33、TouchEvent的分发
View:
1、dispatchTouchEvent
2、 setOnTouchListener的onTouch
3、onTouchEvent
ViewGroup:
1、ViewGroup的dispatchTouchEvent
2、ViewGroup的onInterceptTouchEvent
3、child View的dispatchTouchEvent
4、child View的onTouchEvent
34、