界面的效果用到的技术都很基本, 但实现的思路很新颖, 代码和布局充满各种技巧, 值得学习和借鉴.
效果图:
原理图:
布局代码:
<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.javapublic 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; } }
谢谢!