真是和dog发生的某种关系,接着上一篇,上次做那个划来划去的聊天信息栏
在5天后终于做出来了。。。虽然期间断断续续的做。。真是。。。
总的来说 记录一下:
这个是要做的东西的结构,每个栏都是一个屏幕的宽度,右边的信息栏有个按钮可以滑动显示左边的录音栏
左边的录音栏可以拖动滑出右边的信息栏,大概就是这个一个东西
原本我打算用2个view来做,一个隐藏另一个显示,做做做,做到侧滑的时候原本是用监听来设置onlayout的,
不知道为什么,会抖,后来我就改用scroll做,但是这样一来感觉要管理的数据非常多,什么滚动X啊,可见度啊什么的感觉非常乱。
想了想觉得自定义一个view就是上面这个,做成两个屏幕的宽度,这样就可以只用scroll来做整个动画的管理。
遇到的第一个问题就是设置这个view的宽度,也就是要两个屏幕的宽度。
xml好像一直无法设置两个屏幕宽度这种数据,如果可以请告诉我!
那就只能用获取后再设置
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
screenWidth = wm.getDefaultDisplay().getWidth();
这就是上一篇的来历,研究这个,我发现了View的绘制流程大概是这样的
onFinishInflate() > onMeasure() > onLayout() > onDrawe()
上次讲了,再重复一下把。
onFinishInflate() 看名字应该是在加载布局文件完成之后做的,所以是一个绘制view的过程中只会出现一次的函数我的这个view在默认情况下应该是显示右边这个栏的,所以就是在一开始要滚动一次一个屏幕的宽度,找了半天在这里面做可以,而且就算控件的测量都还没做也可以滚动。。这个我觉得很奇怪。
onMeasure() 这个是会测量控件的真实宽度的方法,为什么强调是真是宽度,是为了和layoutParams的weight区分开来,如果你的空间用的是wrap_content你会发现他的LayoutParams会等于-2,但控件的宽度肯定不是-2,所以在绘制的时候会使用控件的measureHeight这个参数,这个参数也就在Measure之后会更新,就算你把控件的LayoutParams.weight修改成了你自己要的宽度,也需要在measure()修改了控件的measureHeight属性之后,这个改动才会生效。
onLayout() 这个函数应该是大家最熟悉的了,就是移动位置,这个就不细说了。
onDraw() 这个函数好像是不一定触发的,我使用的过程中,只有在给空间设置了背景色之后才触发。
那废话这么多,究竟如何修改自定义空间的宽度呢?
答案就在上祢说的onMeasure()方法中,
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
上面这个函数是用来设置整个控件的参数,注意后面的widthMeasureSpec不能直接使用,要getSize之后才能用。
mMessageBar.measure(screenWidth, mMessageBar.getMeasuredHeight());
上面这个函数可以测量子控件的参数
但是注意我上面说的,这个测量只是测量需要的高宽,然后赋值给measureHeight和measereWidth,并不能真正的修改子控件的位置,不过对于整个控件可以,因为本控件是在上一层的空间中进行layout的。(有点乱,从这开始我们自定义的这个控件就叫本控件,里面的子控件就叫子控件)
所以,onlayout的时候也只需要layout子控件就行,或者说你是无法在这里对本控件进行布局的
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mMessageBar.layout(screenWidth,l, 2 * screenWidth, l + mMessageBar.getMeasuredHeight());
mRecordBar.layout(0, l , screenWidth, l + mMessageBar.getMeasuredHeight());
}
这里设置的是子控件相对与本控件的位置,也就是说,如果本控件的位置在整个屏幕中l是(100,100,100,100),你设置mMessageBar.layout(1,1,1,1)你的子控件就会出现在屏幕中(101,101,101,101)的位置。参数l,t,r,b的值也就是本控件在整个屏幕中的位置,比如你在上一层中设置本控件的layout(100,100,100,100)那么这里的l,t,r,b就是4个100。
提醒几个问题:
1.如果需要给控件引入布局的话
mMessageBar = View.inflate(context, R.layout.bar1, null);
注意最后一个参数是null,虽然api的提示是rootView,是设置会成为这个新控件的父控件,但是实际使用的时候会发生一个问题,如果你这么写
mMessageBar = View.inflate(context, R.layout.bar1, this);
这个mMessageBar就会变成你的自定义控件的布局文件,如果这时候你试图修改这个mMessageBar的layout什么的话,就会一直重复嵌套,导致栈溢出。
2.如果你需要用的子控件的measure参数的话
mMessageBar.measure(screenWidth, mMessageBar.getMeasuredHeight());像我这样,有个问题是一定要在measure之后再调用,我就蛋疼了半天怎么总是获取的measure会慢一拍。
setMeasuredDimension(2 * screenWidth, mMessageBar.getMeasuredHeight());