一个简单的图片滑动展示控件

  首先声明本人Android新人一枚,这是本人第一篇博客,用于对自己知识的巩固,同时把自己写的东西分享出来,希望能帮到有需要的人。

      今天朋友需要一个图片滑动展示的控件,要求图片折叠时除第一张图片,其他都只保留底部一部分可见,可上下滑动展示。

      先讲讲我的思路,本来想用RecyclerView配合隐藏图片来完成的,可是后来一想这样适配性太差,只能用于已知图片数量的情况,于是我决定写一个自定义控件来完成这个需求。这个控件里面最重要的就是控件的大小,绘制图片,控件中图片滑动响应,处理父控件滑动事件的屏蔽。

      首先控大小,我们通过重写onMeasure方法来完成,

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    if (infoList.size() ==0) {

setMeasuredDimension(pWidth, bHeight);//设置控件宽高

    }else {

setMeasuredDimension(pWidth, bHeight +infoList.get(infoList.size() -1).hightTop);//设置控件宽高

    }

}

宽度直接是使用的屏幕宽度,高度我设置了一个默认图片,以这个默认图片的高度bHeight来计算,每多一张图片高度就增加bHeight/4,由于需要对滑动后的控件大小进行改变,我这边用的最后一张图片顶部高度来计算控件高度,效果是一致的。

ViewGroup.LayoutParams layoutParams =this.getLayoutParams();

layoutParams.height =bHeight +infoList.get(infoList.size() -1).hightTop;

this.setLayoutParams(layoutParams);

invalidate();

这是我对滑动后控件大小进行改变的操作。

完成控件大小的设置,就要来绘制图片了,这个我们在onDraw中进行处理,

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

    Rect srcRect =new Rect(0, 0, pWidth, bHeight);//要绘制的bitmap 区域

    if (list.size() ==0) {

Rect destRect =new Rect(0, 0, pWidth, bHeight);//要将bitmap 绘制在屏幕的什么地方

        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);//要将bitmap 绘制在屏幕的什么地方

            canvas.drawBitmap(list.get(i), srcRect, destRect, paint);

        }

}

}

接下来就要处理控件中图片滑动的响应了,首先重写onTouchEvent方法来对手势进行监听,

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN://按下

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

            down_y = (int) event.getY();

break;

        case MotionEvent.ACTION_UP://抬起

            oldy =0;

break;

        case MotionEvent.ACTION_MOVE://移动

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

            moveImageView((int) (event.getY() -down_y));

break;

    }

return true;

}

分别对手指按下,抬起,移动进行了处理,按下时获取手指坐标,移动时获取坐标,计算出移动距离,并对图片进行移动,最后返回true,表示在手势完成后,不会再发送给父类进行处理了。

private void moveImageView(int y) {

if (infoList.size() ==0) {

return;

    }

if (y <0) {//向上滑动

        for (int i =0; 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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容