android listview & toolbar形成的一種炫酷效果(外加一個圓形圖片的實現)
阿新 • • 發佈:2019-02-11
介面的效果用到的技術都很基本, 但實現的思路很新穎, 程式碼和佈局充滿各種技巧, 值得學習和借鑑.
效果圖:
原理圖:
佈局程式碼:
<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; } }
謝謝!