Android View相关笔记

View绘制

1 View树的绘制流程

measure -> layout -> draw  树形递归遍历

2 measure

ViewGroup.LayoutParams     设定宽高,match_parent, wrap_content
MeasureSpec  32位int,最高两位表示测量模式,后30位表示该模式下的尺寸大小
MeasureSpecMode
EXACTLY  父容器为子视图确定容器的大小
AT_MOST 父容器为子视图指定一个最大尺寸
UNSPECIFIED
measure() -> onMeasure() -> setMeasuredDimension()

3 layout

树形结构递归遍历,位置摆放

4 onDraw

invalidate() 请求系统重新渲染,触发onDraw()
requestLayout()  绘画过程中手动调用该方法,触发onMeasure(), onLayout()
当更新View时,如果尺寸大小位置和内容均发生改变,推荐先调用requestLayout(),再invalidate()


事件分发机制

DecorView是PhoneWindow的内部类,PhoneWindow继承抽象类Window.
Activity -> PhoneWindow -> DecorView = StatusBar + RootView -> ViewGroup -> View
dispatchTouchEvent(VG) -> onInterceptTouchEvent(VG) -> onTouchEvent (V)


ListView


recycleBin机制
recycleBin是AbsListView的内部类


ListView优化

  1. convertView重用,添加ViewHolder
  2. getView少做耗时操作
  3. 三级缓存
  4. 开启硬件加速
  5. 减少半透明元素
    public View getView(.., View covertView, ..) {
        ViewHolder holder;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflator….
                … ...
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag(); 
        }

    }

    class ViewHolder {  // 避免多次findViewById()
        private ImageView image;
        private TextView title;
    }




解决在onCreate()过程中获取View的宽高为0的方法
1.监听draw/layout事件
view.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() {
2         @Override
3         public void onGlobalLayout() {
4             mScrollView.post( new Runnable() {
5                 public void run() {
6                     view.getHeight(); // height is ready
7                 }
8             });
9         }
10 });

2.View.post推荐
UI事件队列会按顺序处理事件。在 setContentView() 被调用后,事件队列中会包含一个要求重新layout的 message ,所以任何你post到队列中的东西都会在Layout发生变化后执行。
view.post( new Runnable() {
4             @Override
5 public void run() {
6                 view.getHeight(); // height is ready
7             }
8         });




大房子左右滑动,可点击空白区域
HorizontalScrollView
bitmap.getPixel
android:scrollX

UI线程和工作线程中刷新UI
postInvalidate() invalidate()

雾霾不用于多fragment间切换,并及时销毁
mHazeImage.recycle() ;

自定义控件的属性
<declare-styleable name= "ScrollLayout" >
    <attr name= "defaultScreen" format= "integer" />
    <attr name= "customScreen" format= "integer" />
    <attr name= "customScreenHeight" format= "integer" />
    <attr name= "customScreenScale" format= "integer" />
</declare-styleable>

<com.honeywell.hch.airtouchv2.framework.view.ScrollLayout
    android :id= "@+id/control_filter_scroll"
    android :layout_width= "match_parent"
    android :layout_height= "match_parent"
    android :orientation= "vertical"
    app :customScreen= "1"
    app :customScreenHeight= "70"
    app :defaultScreen= "0 >

帧动画
ImageView loadingImageView = (ImageView) findViewById(R.id. enroll_loading_iv) ;
AnimationDrawable animationDrawable = (AnimationDrawable) loadingImageView.getDrawable() ;
animationDrawable.start() ;


<animation-list
    xmlns: android = " http://schemas.android.com/apk/res/android "
    android :oneshot= "false" >

    <item android :drawable= "@drawable/enroll_loading_1" android :duration= "1000" ></item>
    <item android :drawable= "@drawable/enroll_loading_2" android :duration= "1000" ></item>
    <item android :drawable= "@drawable/enroll_loading_3" android :duration= "1000" ></item>

</animation-list>

属性动画
AnimatorSet popAnimation = new AnimatorSet() ;
popAnimation.playTogether(ObjectAnimator. ofFloat(view , "alpha" , 0 , 1) , ObjectAnimator
        . ofFloat(view , "translationY" , screenHeight - positionY , 0)) ;
popAnimation.setInterpolator( new OvershootInterpolator()) ;
popAnimation.setDuration( mPopUpDuration[index]) ;
popAnimation.start() ;

popAnimation.addListener( new Animator.AnimatorListener() {

动态加载View
<LinearLayout
    android :id= "@+id/all_group_layout"
    android :layout_width= "match_parent"
    android :layout_height= "wrap_content"
    android :orientation= "vertical" >
    <LinearLayout
        android :id= "@+id/group_layout"
        android :layout_width= "match_parent"
        android :layout_height= "wrap_content"
        android :orientation= "vertical" >
    </LinearLayout>
    <LinearLayout
        android :id= "@+id/un_group_layout"
        android :layout_width= "match_parent"
        android :layout_height= "wrap_content"
        android :orientation= "vertical" >
    </LinearLayout>
</LinearLayout>

// add DIY views to one group
LinearLayout oneGroup = new LinearLayout( this) ;
oneGroup.setOrientation(LinearLayout. VERTICAL) ;
AllDeviceGroupTitleView groupTitleView = new AllDeviceGroupTitleView( mContext) ; // 自定义控件
groupTitleView.setBackgroundResource( R.drawable. all_device_group_bg ) ;
groupTitleView.setGroupName(groupName) ;
oneGroup.addView(groupTitleView) ;

// add one group to group list
mGroupLayout = (LinearLayout) findViewById(R.id. group_layout ) ;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams
        (LinearLayout.LayoutParams. MATCH_PARENT , LinearLayout.LayoutParams. WRAP_CONTENT) ;
params. bottomMargin = DensityUtil. dip2px( 20) ;
oneGroup.setLayoutParams(params) ;
mGroupLayout.addView(oneGroupLayout) ;   // 注意区分点击Group还是Device

onTouchEvent()/onTouch() /onLongClick()返回true/false问题
返回true表示该事件已消费,不会被传导下去。
返回false表示事件没有完全消费,将继续传递到子控件处理。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值