ScrollView中嵌套ListView

 TextView显示一行html

TextView及直接父类控件属性layout_heightjava

android:layout_height="wrap_content/match_parent"//内容只显示一行/内容彻底展现

SwipeRefreshLayout布局中添加 CircleView布局android

android.support.v4.widget.SwipeRefreshLayout.java
{
    public SwipeRefreshLayout(Context context, AttributeSet attrs) {
        //构造方法中调用createProgressView函数
        createProgressView();
    }

    private void createProgressView() {
        mCircleView = new CircleImageView(getContext(), CIRCLE_BG_LIGHT, CIRCLE_DIAMETER/2);
        mProgress = new MaterialProgressDrawable(getContext(), this);
        mProgress.setBackgroundColor(CIRCLE_BG_LIGHT);
        mCircleView.setImageDrawable(mProgress);
        //添加布局时是隐藏状态
        mCircleView.setVisibility(View.GONE);
        //把子视图添加到该布局中
        addView(mCircleView);
    }

}

显示CircleView布局app

有两处显示CircleView布局ide

android.support.v4.widget.SwipeRefreshLayout.java
{
    /**
     *该函数是一个Public函数
     *该函数是给外部提供的
     *惟一一个调用startScaleUpAnimation函数的函数
     */
    public void setRefreshing(boolean refreshing) {
        
    }

    /**
     *该函数是一个私有函数,说明有能被该类中的函数调用
     *该函数显示CircleView布局
     */
    private void startScaleUpAnimation(AnimationListener listener) {
        //<1>显示CircleView布局
        mCircleView.setVisibility(View.VISIBLE);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        final int action = MotionEventCompat.getActionMasked(ev);
        switch (action) {
            //ACTION_MOVE在下滑的过程当中才会显示CircleView布局
            case MotionEvent.ACTION_MOVE: {
                //布尔变量mIsBeingDragged为true才会显示CircleView布局
                if (mIsBeingDragged) {
                    // where 1.0f is a full circle
                    //<2>显示CircleView视图
                    if (mCircleView.getVisibility() != View.VISIBLE) {
                        mCircleView.setVisibility(View.VISIBLE);
                    }
                break;
            }
    }



}

mIsBeingDragged布尔变量函数

android.support.v4.widget.SwipeRefreshLayout.java
{
    //开始往下拽的标识,默认值为false.
    private boolean mIsBeingDragged;

    //手指按下去的点的y坐标
    private float mInitialDownY;

    private int mTouchSlop;
    public SwipeRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        //ViewConfiguration.getScaledTouchSlop();触发移动事件的最小距离
        //自定义View处理touch事件的时候,有的时候须要判断用户是否真的存在movie
        //系统提供了这样的方法。表示滑动的时候,手的移动要大于这个返回的距离值才开始移动控件。
        //int TOUCH_SLOP = 8;
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (action) {
            case MotionEvent.ACTION_DOWN: {
                mIsBeingDragged = false;
                //按下时点的y坐标
                final float initialDownY = getMotionEventY(ev, mActivePointerId);
                mInitialDownY = initialDownY;
            }
                break;
            case MotionEvent.ACTION_MOVE:{
                //移动过程当中点的y坐标
                final float y = getMotionEventY(ev, mActivePointerId);
                final float yDiff = y - mInitialDownY;
                if (yDiff > mTouchSlop && !mIsBeingDragged) {
                    //下拉到必定的距离,而且尚未显示
                    mIsBeingDragged = true;
                }
                break;
            }


}

CircleView布局随着滑动位置发生变化布局

布局函数onLayout()this

(width / 2 - circleWidth / 2)spa

mCurrentTargetOffsetTopcode

width / 2 + circleWidth / 2

mCurrentTargetOffsetTop + circleHeight

这里惟一发生变化的是变量mCurrentTargetOffsetTop

android.support.v4.widget.SwipeRefreshLayout.java
{
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int circleWidth = mCircleView.getMeasuredWidth();
        int circleHeight = mCircleView.getMeasuredHeight();
        mCircleView.layout((width / 2 - circleWidth / 2), mCurrentTargetOffsetTop,
                (width / 2 + circleWidth / 2), mCurrentTargetOffsetTop + circleHeight);
    }
}

测量函数

android.support.v4.widget.SwipeRefreshLayout.java
{
    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mCircleView.measure(MeasureSpec.makeMeasureSpec(mCircleWidth, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(mCircleHeight, MeasureSpec.EXACTLY));
        if (!mUsingCustomStart && !mOriginalOffsetCalculated) {
            mOriginalOffsetCalculated = true;
            mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();
        }
    }
}

CircleView布局以缩减的方式消失

PullRefreshLayout.java {
    private void startScaleDownAnimation(Animation.AnimationListener listener) {
        mScaleDownAnimation = new Animation() {
            @Override
            public void applyTransformation(float interpolatedTime, Transformation t) {
                setAnimationProgress(1 - interpolatedTime);
            }
        };
        mScaleDownAnimation.setDuration(SCALE_DOWN_DURATION);
        mCircleView.setAnimationListener(listener);
        mCircleView.clearAnimation();
        mCircleView.startAnimation(mScaleDownAnimation);
    }
}

箭头随着下拉的距离透明度的改变

SwipeRefreshLayout.java
{
    private static final int STARTING_PROGRESS_ALPHA = (int) (.3f * MAX_ALPHA);

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        final int action = MotionEventCompat.getActionMasked(ev);
        switch (action) {
            case MotionEvent.ACTION_MOVE: {
                    mProgress.showArrow(true);

            }

        }
        
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = MotionEventCompat.getActionMasked(ev);

        switch (action) {
            case MotionEvent.ACTION_MOVE:
                mProgress.setAlpha(STARTING_PROGRESS_ALPHA);
                break;
        }
    }
}

 

ListView

RecyclerView

Bitmap

public final class Bitmap implements Parcelable {

}

Bitmap与Matrix

高效显示Bitmap

https://developer.android.com/topic/performance/graphics/index.html