A simple picture sliding display control

      First of all, I declare that I am an Android newcomer. This is my first blog. It is used to consolidate my knowledge and share what I have written, hoping to help those in need.

      Today, my friend needs a control for sliding display of pictures. When the picture is folded, except for the first picture, only the bottom part is left visible, and it can be displayed by sliding up and down.

      Let me talk about my ideas first. I originally wanted to use RecyclerView with hidden pictures to complete it, but then I thought that the adaptability was too poor and could only be used when the number of pictures is known, so I decided to write a custom control to complete it. this demand. The most important thing in this control is the size of the control, drawing pictures, sliding response of pictures in the control, and handling the shielding of sliding events of the parent control.

      First control the size, we do it by overriding the onMeasure method,

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    if (infoList.size() == 0) {
        setMeasuredDimension( pWidth , bHeight ) ; //Set the width and height of the control
     } else {
        setMeasuredDimension( pWidth , bHeight + infoList .get( infoList .size() - 1 ) .hightTop ) ; //Set the width and height of the control
     }

}

The width is directly the width of the screen used, and the height I set a default image, which is calculated by the height bHeight of this default image, and the height of each additional image increases by bHeight/4. Since the size of the sliding control needs to be changed, I The top height of the last image used here is used to calculate the height of the control, and the effect is the same.


This is what I do to change the size of the controls after swiping.

After completing the setting of the control size, it is time to draw the picture, which we process in onDraw,

@Override
 protected void onDraw (Canvas canvas) {
     super .onDraw(canvas) ;
     Rect srcRect = new Rect( 0 , 0 , pWidth , bHeight ) ; //The bitmap area to be drawn
 if ( list .size() == 0 ) {    
        Rect destRect = new Rect( 0 , 0 , pWidth , bHeight ) ; //Where to draw the bitmap on the screen
         canvas.drawBitmap( bitmap , srcRect , destRect , paint ) ;
     } else {
         for ( int i = list .size () - 1 ; i >= 0 ; i--) {
            BitmapInfo bitmapInfo = infoList .get(i) ;
             Rect destRect = new Rect(bitmapInfo. widthLeft , bitmapInfo. hightTop , bitmapInfo. widthRight , bitmapInfo. hightTop + bHeight ) ; //Where to draw the bitmap on the screen
             canvas.drawBitmap( list .get(i) , srcRect , destRect , paint ) ;
         }
    }
}

The next step is to deal with the response of the picture sliding in the control. First, rewrite the onTouchEvent method to monitor the gesture.

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN://按下
down_y = (int) event.getY();
            break;
        case MotionEvent.ACTION_UP://抬起
oldy = 0;
            break;
        case MotionEvent.ACTION_MOVE://移动
moveImageView((int) (event.getY() - down_y));
                                                break;
    }
    return true;
}

The finger presses, lifts, and moves are processed respectively, the finger coordinates are obtained when the finger is pressed, the coordinates are obtained when moving, the moving distance is calculated, and the picture is moved, and finally returns true, indicating that after the gesture is completed, it will not be used again. Sent to the parent class for processing.

private void moveImageView(int y) {
    if (infoList.size() == 0) {
        return;
    }
    if (y < 0) {//向上滑动
for (int i = 0; i < infoList.size(); i++) {        
            BitmapInfo bitmapInfo = infoList.get(i);
            if (i == 0) {
                if (bitmapInfo.hightTop > (-infoList.size() + 1) * bHeight) {
                    bitmapInfo.setHightTop(bitmapInfo.hightTop + y - oldy);
                    if (bitmapInfo.hightTop < (-infoList.size() + 1) * bHeight) {
                        bitmapInfo.setHightTop((-infoList.size() + 1) * bHeight);
                    }
                }
            } else {
                BitmapInfo lastBitmapInfo = infoList.get(i - 1);
                if (bitmapInfo.hightTop > (-infoList.size() + i + 1) * bHeight && lastBitmapInfo.hightTop <= -(4 - i) * bHeight / 4) {
                    bitmapInfo.setHightTop(bitmapInfo.hightTop + y - oldy);
                    if (bitmapInfo.hightTop < (-infoList.size() + i + 1) * bHeight) {
                        bitmapInfo.setHightTop((-infoList.size() + i + 1) * bHeight);
                    }
                }
            }
        }
    } else {//向下滑动
        for (int i = list.size() - 1; i >= 0; i--) {
            BitmapInfo bitmapInfo = infoList.get(i);
            if (bitmapInfo.hightTop < i * bHeight / 4) {
                bitmapInfo.setHightTop(bitmapInfo.hightTop + y - oldy);
                if (bitmapInfo.hightTop > i * bHeight / 4) {
                    bitmapInfo.setHightTop(i * bHeight / 4);
                }
            }
        }
    }
    oldy = y;
    ViewGroup.LayoutParams layoutParams = this.getLayoutParams();
    layoutParams.height = bHeight + infoList.get(infoList.size() - 1).hightTop;
    this.setLayoutParams(layoutParams);
    invalidate();
}

由于在移动图片是会用到上一步移动的距离oldy,所以在抬起手指的手势处理中多oldy进行初始化,为了更好的处理图片移动时,位置的变化,我用了一个内部bean类来记录图片的位置信息,

private class BitmapInfo {
    private int widthLeft;
    private int hightTop;
    private int widthRight;
    private int hightBottom;

    BitmapInfo(int widthLeft, int hightTop, int widthRight, int hightBottom) {
        this.widthLeft = widthLeft;
        this.hightTop = hightTop;
        this.widthRight = widthRight;
        this.hightBottom = hightBottom;
    }

    void setHightTop(int hightTop) {
        this.hightTop = hightTop;
    }
}

到这里控件其实已经完成了,不过在我们把控件放到ScrollView中时,我们会发现我们的图片滑动不了,我们的手指触摸事件被ScrollView屏蔽了,这里我们就要在对应的触摸事件中队父控件的屏蔽事件进行屏蔽,

getParent().requestDisallowInterceptTouchEvent(true);//屏蔽父类的事件屏蔽

,到这里整个控件就大功告成了。

总结:这是一个很简单的控件,没有花哨的效果,这里面会用到Android自定义控件及事件分发机制的知识。

这边是源码:https://github.com/flychen11/MySlideImageView.git


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324515732&siteId=291194637