效果图如下
activity布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.npi.blureffect.ListViewActivity" > <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" > </ListView> <com.npi.blureffect.ScrollableImageView android:id="@+id/blurred_image_header" android:layout_width="match_parent" android:layout_height="50dp" android:background="#e8e8e8" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="false" android:layout_alignParentRight="false" android:layout_alignParentTop="false" android:layout_centerVertical="true" android:src="@drawable/demo02" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="20dp" android:text="Button" /> </RelativeLayout>
listView的header的布局,这里应该和头部的模糊view一样
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.npi.blureffect.ListViewActivity" > <com.npi.blureffect.ScrollableImageView android:id="@+id/blurred_image_header" android:layout_width="match_parent" android:layout_height="50dp" android:background="#e8e8e8" /> </RelativeLayout>
package com.npi.blureffect; import java.util.ArrayList; import java.util.List; import java.util.zip.Inflater; import com.situ.android.adapter.CommonAdapter; import com.situ.android.adapter.ViewHolder; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.MeasureSpec; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ImageView; import android.widget.ListView; public class ListViewActivity extends Activity { ScrollableImageView header; ListView listView; Bitmap screen; View listHeader; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list_view); listView = (ListView) findViewById(R.id.listView1); header = (ScrollableImageView) findViewById(R.id.blurred_image_header); List<Integer> contents = new ArrayList<Integer>(); contents.add(R.drawable.demo01); contents.add(R.drawable.demo02); contents.add(R.drawable.demo03); contents.add(R.drawable.demo04); contents.add(R.drawable.demo05); contents.add(R.drawable.demo06); contents.add(R.drawable.demo07); contents.add(R.drawable.demo08); contents.add(R.drawable.demo09); contents.add(R.drawable.demo10); contents.add(R.drawable.demo11); contents.add(R.drawable.demo12); contents.add(R.drawable.demo13); contents.add(R.drawable.demo14); contents.add(R.drawable.demo15); listView.setAdapter(new CommonAdapter(ListViewActivity.this,R.layout.list_activity_item,contents) { @Override public void convert(ViewHolder holder, int position, Object object) { // TODO Auto-generated method stub ImageView img = (ImageView)holder.getView(R.id.imageView1); img.setImageResource((Integer)object); } }); initListView(listView, header); } int totalHeight=0; int initHeight = 0; private void initListView(final ListView listView,final ScrollableImageView header){ LayoutInflater inflater = getLayoutInflater(); listHeader = inflater.inflate(R.layout.list_header, null); listView.addHeaderView(listHeader); listView.setOnScrollListener(new OnScrollListener() { int X = 0; int Y = 0; int height = 0; /** * 获取当前滑动的精准位置,仅能用于行高均相同的listview * @param mListView * @return */ public int getScrollY(final AbsListView mListView) { mListView.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub View c = mListView.getChildAt(0); if (c == null) { return ; } int firstVisiblePosition = mListView.getFirstVisiblePosition(); int top = c.getTop(); // Log.i("Alex", "子元素的top是"+top+"头的高度是"+listHeader.getHeight()+" :"+listHeader.getMeasuredHeight()); //重中之重的方法!!!!!!!!!!!!!!!!!!!!!!! Log.i("Alex", "计算结果是 "+top+"+"+(firstVisiblePosition-1)+" *"+c.getHeight()+" +"+listHeader.getHeight()+" :"+listHeader.getMeasuredHeight()); if(c.getHeight()==listHeader.getHeight()){ height = -top + (firstVisiblePosition) * c.getHeight() ; }else{ height = -top + (firstVisiblePosition-1) * c.getHeight()+listHeader.getHeight() ; } } }); return height; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // TODO Auto-generated method stub Log.i("Alex", "listView滚动状态改变了:::"+scrollState); switch(scrollState){ case OnScrollListener.SCROLL_STATE_IDLE://空闲状态 Log.i("Alex", "现在是空闲状态"); break; case OnScrollListener.SCROLL_STATE_FLING://滚动状态 Log.i("Alex", "现在是滚动状态"); break; case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL://触摸后滚动 Log.i("Alex", "现在是惯性状态"); break; } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub // Log.i("Alex", "正在滚动。。第一个可见item是"+firstVisibleItem+" 可见item的数量是"+visibleItemCount+" /"+totalItemCount); // X = listView.getScrollX(); Y = getScrollY(view); if(Y<initHeight){ Log.i("Alex", "现在是刚进来"); } if(Y>initHeight && Y >totalHeight-listHeader.getHeight()){ Log.i("Alex", "正在重新截图。。。................................................................................。。。。。。。。。。。。"); view.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Bitmap subScreen = Blur.fastblur(ListViewActivity.this, getbBitmap(listView), 15); screen = concactBitmapVertical(screen, subScreen); subScreen.recycle();//消除内存 totalHeight = screen.getHeight(); header.setoriginalImage(screen); } }); } Log.i("Alex", "现在要显示到:"+Y); header.handleScroll(Y, 0); } }); listView.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub screen = getbBitmap(listView); initHeight = screen.getHeight(); screen = Blur.fastblur(ListViewActivity.this, screen, 15); totalHeight = screen.getHeight(); header.setoriginalImage(screen); } }); } /** * 截图listview,这个截图方法有bug,在快速滑动和慢速滑动的时候截图结果不同 * **/ public static Bitmap getbBitmap(ListView listView) { int h = 0; Bitmap bitmap = null; // 获取listView实际高度 Log.i("Alex", "子元素数量是"+listView.getChildCount()); for (int i = 0; i < listView.getChildCount(); i++) { h += listView.getChildAt(i).getHeight(); } Log.d("Alex", "实际高度:" + h); Log.d("Alex", "list 高度:" + listView.getHeight()); // 创建对应大小的bitmap bitmap = Bitmap.createBitmap(listView.getWidth(), h, Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(bitmap); listView.draw(canvas); return bitmap; } /** * 这个方法不能用于listView中的contentView,不然被测量之前的contentVIew就都没了 * @param view * @return */ public static Bitmap convertViewToBitmap(View view) { view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); view.buildDrawingCache(); Bitmap bitmap = view.getDrawingCache(); if (bitmap != null) { System.out.println("这不是nullde1"); Log.d("nullde1", "nullde1"); } else { System.out.println("这nullnulllnulnlul"); } return bitmap; } /** * 将两张位图拼接成一张(横向拼接) * * @param first * @param second * @return */ private Bitmap concactBitmapHorizantal(Bitmap first, Bitmap second) { int width =first.getWidth() + second.getWidth(); int height = Math.max(first.getHeight(), second.getHeight()); Bitmap result = Bitmap.createBitmap(width, height, Config.ARGB_8888); Canvas canvas = new Canvas(result); canvas.drawBitmap(first, 0, 0, null); canvas.drawBitmap(second, first.getWidth(), 0, null); return result; } /** * 将两张位图拼接成一张(横向拼接) * * @param first * @param second * @return */ private Bitmap concactBitmapVertical(Bitmap first, Bitmap second) { int width =Math.max(first.getWidth(), second.getWidth()); int height = first.getHeight()+second.getHeight(); Bitmap result = Bitmap.createBitmap(width, height, Config.ARGB_4444); Canvas canvas = new Canvas(result); canvas.drawBitmap(first, 0, 0, null);//先画第一个 canvas.drawBitmap(second, 0, first.getHeight(), null);//在第一个的下面画第二个 return result; } }