【閒來無事】仿知乎廣告Banner的切換功能

開頭

看到知乎中,文章下側會跟着一個廣告banner,上下滑動文章時會根據方向,進行扇形的切換。git

閒來無事就寫個玩玩,本人菜雞,初步想的就是兩層ImageView重疊,對上層的IV進行裁剪操做,遂,直接開擼(demo功能演示,代碼可能不漂亮還請見諒)。github

佈局

佈局大體樣式canvas

ScrollView
    content view
        framelayout/relativelayout都可
                imageView id:iv_below
                imageView id:iv_above
        framelayout/relativelayout都可
    content view
複製代碼

實現

咱們只須要對 iv_above 進行裁剪操做便可bash

首先得到iv_above的bitmap網絡

bmAbove = ((BitmapDrawable)ivOrange.getDrawable()).getBitmap();
複製代碼

對滾動進行監聽:ide

(實際上知乎的功能是對滑動方向進行判斷後,直接開始進行動畫,扇形半徑並不跟滑動距離有關聯,當滑動方向與上次的相反時,中止上次的動畫,再reverse,這樣作的好處就是在滑動時進行了最少的運算,避免了潛在的滑動卡頓,我仍是直接關聯扇形半徑和滑動距離)佈局

private float screenWidth;
    private float threshold = 500;
        scrollView.setListener(new MyScrollView.onScrollListener() {
            @Override
            public void onScroll(int l, int t, int oldl, int oldt) {
                float curY = (float)t;
                if(t > oldt){
                    //scroll down
                    isScrollUp = false;
                    float r = curY / threshold ;
                    ivOrange.setImageBitmap(circleBitmap(bmOrange, r * screenWidth));
                }else{
                    isScrollUp = true;
                    float r = curY / threshold ;
                    ivOrange.setImageBitmap(circleBitmap(bmOrange, r * screenWidth));
                }
            }
        });
複製代碼

裁剪優化

private Bitmap circleBitmap(Bitmap o,float radius){
        Bitmap outputBm = Bitmap.createBitmap(o.getWidth(),o.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(outputBm);
        final Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);

        final Rect rect = new Rect(0,0,o.getWidth(),o.getHeight());
        canvas.drawARGB(0,0,0,0);
        canvas.drawCircle(0,0,radius,paint );
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(o,rect,rect,paint);
        return outputBm;
    }
複製代碼

用到paint.setXfermode,傳入new PorterDuffXfermode 能夠對2d圖像的合成模式進行設置。 (.setXfermode這個方法功能很複雜也很強大,有興趣的能夠去百度一下)動畫

總計有18個合成模式:ui

CLEAR/ SRC/ DST/ SRC_OVER/ DST_OVER SRC_IN/ DST_IN/ SRC_OUT/ DST_OUT/ SRC_ATOP/ DST_ATOP/ XOR/ DARKEN/ LIGHTEN/ MULTIPLY/ SCREEN/ ADD/ OVERLAY/

合成樣式以下圖(來源自網絡):

這裏是用的是SRC_IN 模式,經過繪製一個圓形(半徑radius,並會增減),與原bmAbove重疊,以後取相交的部分做爲bitmap返回,達到裁剪的效果。

結束

至此整個功能就實現了,固然代碼還有不少能夠優化的地方,以及其餘實現方式,歡迎你們留言一塊兒交流。

demo地址:

[github.com/bladeofgod/…](demo 地址)

相關文章
相關標籤/搜索