android listview & toolbar形成的一种炫酷效果(外加一个圆形图片的实现)

界面的效果用到的技术都很基本, 但实现的思路很新颖, 代码和布局充满各种技巧, 值得学习和借鉴.

效果图:


原理图:


布局代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:roundIcon="http://schemas.android.com/apk/res-auto"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <!--模块一-->
    <ImageView
        android:id="@+id/top_bg"
        android:scaleType="fitXY"
        android:src="@drawable/example"
        android:layout_width="match_parent"
        android:layout_height="220dp" />

    <View
        android:id="@+id/filter_bg"
        android:background="#00000000"
        android:layout_width="match_parent"
        android:layout_height="220dp" />

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:background="#00000000"
        android:minHeight="?attr/actionBarSize"
        app:popupTheme="@style/Theme.AppCompat.Light.DarkActionBar"
        app:theme="@style/Theme.AppCompat" />
    <TextView
        android:layout_marginTop="155dp"
        android:textSize="30sp"
        android:text="My Flexible Space"
        android:textColor="#ffffff"
        android:id="@+id/title"
        android:padding="16dp"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />


    <com.temp.lin.temp1.RoundIcon
        android:id="@+id/round_icon"
        android:src="@drawable/round_icon"
        roundIcon:borderWidth="0dp"
        roundIcon:borderColor="#cfcfcf"
        android:layout_marginBottom="-40dp"
        android:layout_marginRight="22dp"
        android:layout_alignParentRight="true"
        android:layout_marginTop="180dp"
        android:layout_width="80dp"
        android:layout_height="80dp" />
    <!--模块一-->

    <!--模块二-->
    <!--
    wrap_content会全屏的了
    作为listview的背景, 但不包括header view的背景
    -->
    <View
        android:visibility="gone"
        android:id="@+id/list_background"
        android:background="#ffffff"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <!--
    ListView 不能设置background, 不然在代码添加的headerView就也一样有background了
    ListView背景默认是透明的
    -->
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
    <!--模块二-->




</RelativeLayout>

实现代码:

RoundIcon.java
public class RoundIcon extends ImageView {
    private Paint borderPaint;
    private int cx=-1,cy=-1,radius;
    private int borderColor,borderWidth;
    public RoundIcon(Context context) {
        super(context,null);
    }
    public RoundIcon(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a=getResources().obtainAttributes(attrs, R.styleable.roundIcon);
        borderColor=a.getColor(R.styleable.roundIcon_borderColor,0xffffffff);
        borderWidth= (int) a.getDimension(R.styleable.roundIcon_borderWidth, 0f);
        a.recycle();
        borderPaint=new Paint();
        borderPaint.setAntiAlias(true);
        borderPaint.setStyle(Paint.Style.STROKE);
        borderPaint.setStrokeWidth(borderWidth);
        borderPaint.setColor(borderColor);
        borderPaint.setDither(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);
        if (cx==-1){cx=getWidth()/2; radius=cx-borderWidth/2;}
        if (cy==-1){cy=getHeight()/2;}
        //draw border
        canvas.drawCircle(cx,cy,radius,borderPaint);
        //draw round picture
        canvas.drawBitmap(getRoundBitmap(((BitmapDrawable) getDrawable()).getBitmap(), radius*2),
                borderWidth / 2, borderWidth / 2, null);
    }

    private Bitmap getRoundBitmap(Bitmap bitmap, int len) {
        Bitmap squareBitmap,scaleBitmap;
        int bitmapW=bitmap.getWidth();
        int bitmapH=bitmap.getHeight();
        //
        Matrix matrix = new Matrix();
        float scale=Math.max(len/(bitmapW+0.0f),len/(bitmapH+0.0f));
        matrix.postScale(scale,scale);
        scaleBitmap=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        //
        bitmapW=scaleBitmap.getWidth();
        bitmapH=scaleBitmap.getHeight();
        if (bitmapH==bitmapW){
            squareBitmap=scaleBitmap;
        }else{
            int size=bitmapH<bitmapW?bitmapH:bitmapW;
            if (size!=len) size=len;
            squareBitmap=Bitmap.createBitmap(scaleBitmap,0,0,size,size);
        }
        //
//        Log.e("len w h",len+" "+squareBitmap.getWidth()+" "+squareBitmap.getHeight());
        Bitmap output=Bitmap.createBitmap(squareBitmap.getWidth(),squareBitmap.getHeight(),
                Bitmap.Config.ARGB_8888);
        Canvas myCanvas=new Canvas(output);
        Paint mPaint=new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setFilterBitmap(true);
        mPaint.setDither(true);
        //PorterDuffXfermode一定要先画一个背景之后才能使用
        //不然画不出东西
        myCanvas.drawCircle(cx,cy,radius,mPaint);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        myCanvas.drawBitmap(squareBitmap,0,0,mPaint);
        return output;
    }
}

SildingUpWithImgActivity.java
public class SildingUpWithImgActivity extends Activity {

    int topBgHeight,titleMarginTop;
    private ImageView topBg;
    private View filterBg,listBg;
    private TextView title;
    private RoundIcon roundIcon;
    private ListView listView;
    private Toolbar toolbar;
    private int preScrollDist=0,curScrollDist=0;
    private ScaleAnimation roundIconAnimSmall,roundIconAnimBig;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        final View headerView=new View(this);
        headerView.setClickable(true);
        //
        topBg= (ImageView) findViewById(R.id.top_bg);
        filterBg=findViewById(R.id.filter_bg);
        topBg.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                topBg.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                topBgHeight = topBg.getLayoutParams().height;
                //
                AbsListView.LayoutParams layoutParams=
                        new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT,topBgHeight);
                headerView.setLayoutParams(layoutParams);
                ViewGroup.LayoutParams la=filterBg.getLayoutParams();
                //
                listBg.setTranslationY(topBgHeight);
            }
        });
        //
        title= (TextView) findViewById(R.id.title);
        title.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                title.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                titleMarginTop=((RelativeLayout.LayoutParams)title.getLayoutParams()).topMargin;
            }
        });
        //
        roundIcon= (RoundIcon) findViewById(R.id.round_icon);
        //
        listBg=findViewById(R.id.list_background);
        //
        listView= (ListView) findViewById(R.id.listview);
        listView.addHeaderView(headerView);
        listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getDatas()));
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (topBgHeight==0) return;
                int dist = getScrollDist();
                setTopBgParams(dist / 2);
                setTitleParams(dist);
                setRoundIconParams(dist);
                setListViewParams(topBgHeight + dist);
            }
        });
        //
        toolbar= (Toolbar) findViewById(R.id.toolbar);
    }

    private int getScrollDist() {
        if (listView.getChildCount()<1) return 0; //不然会空指针错误
        int firstVisiblePosition=listView.getFirstVisiblePosition();
        preScrollDist=curScrollDist;
        curScrollDist=-listView.getChildAt(0).getTop();
        //
        if (firstVisiblePosition>=1){
            curScrollDist+=topBgHeight;
            firstVisiblePosition--;
        }
        View view=listView.getChildAt(1);
        if (view!=null){
            curScrollDist+=firstVisiblePosition*view.getHeight();
        }
        //
//        int dist=curScrollDist-preScrollDist;
//        Log.e("dist",curScrollDist+"");
        return -curScrollDist;
    }

    private void setRoundIconParams(int dist) {
        int max=0;
        int min=-(topBgHeight-roundIcon.getHeight()/2);
        float transY=getBetween(min,max,dist);
        roundIcon.setTranslationY(transY);
//        Log.e("setRoundIconParams transY min",transY+" "+min);
        if (transY/min>0.5&&roundIconAnimSmall==null){
            if (roundIconAnimBig!=null){
                roundIconAnimBig.cancel();
                roundIconAnimBig=null;
            }
            roundIconAnimSmall=new ScaleAnimation(1f,0f,1f,0f);
            roundIconAnimSmall.setFillAfter(true);
            roundIconAnimSmall.setDuration(300);
            roundIcon.startAnimation(roundIconAnimSmall);
        }else if (transY/min<=0.5&&roundIconAnimBig==null){
            if (roundIconAnimSmall!=null){
                roundIconAnimSmall.cancel();
                roundIconAnimSmall=null;
            }
            roundIconAnimBig=new ScaleAnimation(0f,1f,0f,1f);
            roundIconAnimBig.setFillAfter(true);
            roundIconAnimBig.setDuration(300);
            roundIcon.startAnimation(roundIconAnimBig);
        }
    }

    private void setTitleParams(int dist) {
        int min=-(topBgHeight-title.getMeasuredHeight());
        int max=0;
        float transY=getBetween(min, max, dist);
        title.setTranslationY(transY);
        float ratio=1-transY/min/3;
//        Log.e("setTitleParams transY min",transY+" "+min);
        title.setPivotX(0);
        title.setPivotY(0);
        title.setScaleX(ratio);
        title.setScaleY(ratio);
    }

    private void setTopBgParams(int dist) {
        int min=-topBgHeight/2;
        int max=0;
        float transY=getBetween(min, max, dist);
        topBg.setTranslationY(transY);
        filterBg.setTranslationY(transY);
        //
        float ratio=transY/min;
        //mask: 0~255(滑到顶部)
        int mask= (int) (ratio*0xff);
//        Log.e("mask",color+"");
        if (mask<160){
            int color=0x00000000|(mask<<24);
            filterBg.setBackgroundColor(color);
            toolbar.setBackgroundColor(0x00000000);
        }else{
            int color=0xff000000;
            filterBg.setBackgroundColor(color);
            toolbar.setBackgroundColor(color);
        }
    }

    private void setListViewParams(int dist) {
        int max=topBgHeight;
        int min=0;
        listBg.setTranslationY(getBetween(min,max,dist));
    }

    private int getBetween(int min,int max, int value){
        return Math.min(Math.max(min,value),max);
    }

    private String[] getDatas() {
        String[] datas=new String[40];
        for (int i=0;i<datas.length;i++){
            int j=i+1;
            datas[i]="data id: "+j;
        }
        return datas;
    }

}

谢谢!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值