美文网首页
【Android群英传】——第三章:Android控件架构与自定

【Android群英传】——第三章:Android控件架构与自定

作者: 感同身受_ | 来源:发表于2020-01-28 21:43 被阅读0次

    之前学习了《Android群英传》,不过当时时间很零碎,很多问题没有深究、理解,趁着放假,认真回顾了之前的代码,同时解决了之前没有解决的问题,这里只是记录一下写Demo过程中遇到的问题及解决办法,具体笔记都在书上(感觉书上记录笔记方便一点),源代码放在我的GitHub

    3.2 View的测量

    1. 重写onMeasure方法,这里自己调用setMeasuredDimension方法,就不需要将测量值传到super.onMeasure()中,在View里面去调用setMeasuredDimension方法
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
        }
    
    1. 测量长宽的模板代码
        private int measureWidth(int measureSpec){
            int result = 0;
            int specMode = MeasureSpec.getMode(measureSpec);//得到测量模式
            int specSize = MeasureSpec.getSize(measureSpec);//得到测量值
    
            if (specMode == MeasureSpec.EXACTLY){
                result = specSize;
            }else{//若不为EXACTLY模式,则设置默认大小
                result = 200;
                if (specMode == MeasureSpec.AT_MOST){
                    result = Math.min(result,specSize);
                }
            }
            return result;
        }
    

    3.6 自定义View

    1. 闪动的文字效果
      这里继承TextView的时候,会报错,但是运行不会受影响
      )布局:
    <com.example.systemwidgettest.MyTextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_below="@+id/myTopBar"
            android:text="Android"
            android:textSize="28sp"
            android:layout_centerHorizontal="true"/>
    

    2)代码:


    闪动的文字效果
    1. 创建复合控件
      1)布局:
    <com.example.systemwidgettest.MyTopBar
    
            android:id="@+id/myTopBar"
            android:layout_width="wrap_content"
            android:layout_height="40dp"
            custom:leftBackground="@drawable/ic_launcher_background"
            custom:leftText="Back"
            custom:leftTextColor="#FFFFFF"
            custom:rightBackground="@drawable/ic_launcher_background"
            custom:rightText="More"
            custom:rightTextColor="#FFFFFF"
            custom:title="消息"
            custom:titleTextColor1="#CA1212"
            custom:titleTextSize="10sp"/>
    

    2)代码:


    创建复合控件
    1. 重写View来实现全新的控件
      1)布局:
    <com.example.systemwidgettest.MyCanvas
            android:id="@+id/myCanvas"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/myTopBar"/>
    

    2)代码:


    重写View来实现全新的控件
    1. 音频条形图
      1)布局:
    <com.example.systemwidgettest.MyAudio
            android:id="@+id/myAudio"
            android:layout_below="@+id/myTopBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    

    2)代码:


    音频条形图

    3.7 自定义ViewGroup

    1)布局:

    <com.example.systemwidgettest.MyViewGroup
            android:id="@+id/myViewGroup"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="fitXY"
                android:src="@drawable/bg" />
    
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="fitXY"
                android:src="@drawable/bg2" />
    
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="fitXY"
                android:src="@drawable/bg3" />
    
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="fitXY"
                android:src="@drawable/bg4" />
    
        </com.example.systemwidgettest.MyViewGroup>
    

    2)代码:


    自定义ViewGroup
    1. child.layout(l,i*mScreenHeight,r,(i+1)*mScreenHeight);写这个方法时,第二个参数我没有写i*,导致界面无法显示
    @Override
        public void onLayout(boolean changed,int l,int t,int r,int b){
            int childCount = getChildCount();
            Log.d(TAG, "onLayout: childCount: "+childCount);//有n个子view
            //设置ViewGroup的高度
            MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
            mlp.height = mScreenHeight*childCount;
            Log.d(TAG, "onLayout: mScreenHeight: "+mScreenHeight);
            setLayoutParams(mlp);
            //将子view放到viewGroup中
            for (int i = 0; i < childCount; i++) {
                View child = getChildAt(i);
                if (child.getVisibility() != View.GONE){
                    //ViewGroup在执行Layout的过程中,通过遍历来调用View的Layout方法,并传入参数确定其位置
                    child.layout(l,i*mScreenHeight,r,(i+1)*mScreenHeight);
                }
            }
        }
    
    1. 在onTouchEvent()方法中,在case MotionEvent.ACTION_MOVE:分支上,书上写的是if(getScaleY()>getHeight()-mScreenHeight)判断为>,但是实际应该为<才能正常运行,原因写在代码上了
    //实现ViewGroup的触控事件和滑动事件
        @Override
        public boolean onTouchEvent(MotionEvent event){
            int y = (int) event.getY();
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    mLastY = y;
                    mStart = getScrollY();//手指起始位置
                    break;
                case MotionEvent.ACTION_MOVE:
                    if(!mScroller.isFinished()){
                        mScroller.abortAnimation();
                    }
                    int dy = mLastY-y;
                    if(getScrollY()<0){
                        dy = 0;
                    }
                    //之前得判断为getScaleY()>getHeight()-mScreenHeight
                    //这段代码加上后,向下滑,不能滑动,因为getScaleY()方法返回为1
                    //getHeight()方法返回大于2621,mScreenHeight=2621
                    //所以这个判断恒为真
                    //所以我觉得是getScaleY()<getHeight()-mScreenHeight
                    if(getScaleY()<getHeight()-mScreenHeight){
                        dy = 0;
                    }
                    scrollBy(0,dy);//手指滑动时让viewGroup的所有子view跟着滑动 dy 距离
                    mLastY = y;
                    break;
                case MotionEvent.ACTION_UP:
                    mEnd = getScrollY();//记录触摸终点
    //                int dScrollY = (int) (mEnd - mStart);//得到手指滑动距离
                    int dScrollY = checkAlignment();
                    if (dScrollY>0) {
                        if (dScrollY<mScreenHeight/3){//小于一定距离
                            mScroller.startScroll(0, (int) getScrollY(),0,-dScrollY);//回到原来的位置
                        }else{//若超过一定距离
                            mScroller.startScroll(0, (int) getScrollY(),0,mScreenHeight-dScrollY);//使用Scroller类平滑到下一个子view
                        }
                    }else{
                        if(-dScrollY<mScreenHeight/3){
                            mScroller.startScroll(0, (int) getScrollY(),0,-dScrollY);
                        }else{
                            mScroller.startScroll(0, (int) getScrollY(),0,-mScreenHeight-dScrollY);
                        }
                    }
                    break;
            }
            postInvalidate();
            return true;//将继续向上传递审核
        }
    
    1. case MotionEvent.ACTION_UP:分支上,我把getScrollY()方法,写成了getScaleY()方法,导致返回的结果始终为1(因为getScaleY()方法返回的是缩放值,但是我没有对他进行缩放操作,所以返回的缩放值始终是100%,即1),getScrollY()是返回视图的滚动顶部位置,是值位于[0,mScreenHeight]的。
                case MotionEvent.ACTION_UP:
                    mEnd = getScrollY();//记录触摸终点
    //                int dScrollY = (int) (mEnd - mStart);//得到手指滑动距离
                    int dScrollY = checkAlignment();
                    if (dScrollY>0) {
                        if (dScrollY<mScreenHeight/3){//小于一定距离
                            mScroller.startScroll(0, (int) getScrollY(),0,-dScrollY);//回到原来的位置
                        }else{//若超过一定距离
                            mScroller.startScroll(0, (int) getScrollY(),0,mScreenHeight-dScrollY);//使用Scroller类平滑到下一个子view
                        }
                    }else{
                        if(-dScrollY<mScreenHeight/3){
                            mScroller.startScroll(0, (int) getScrollY(),0,-dScrollY);
                        }else{
                            mScroller.startScroll(0, (int) getScrollY(),0,-mScreenHeight-dScrollY);
                        }
                    }
                    break;
    

    源代码放在我的GitHub

    相关文章

      网友评论

          本文标题:【Android群英传】——第三章:Android控件架构与自定

          本文链接:https://www.haomeiwen.com/subject/tnpmthtx.html