Android GridView 选择item 放大的动画

最近有用到在GridView 中选择单个的Item 时,需要将选择的Item 放大的需求.就网上查找了一下相关资料,同时查看了一下android相关的源码.
这里记录一下,以便日后回忆和继续完善这个笔记.

首先我们要知道在上面描述的情况下,一个ViewGroup 会有几个child view.我们如果只是直接使用缩放动画去放大那个选中View 会发现一个问题:选中的view 放大之后会被parent 的其他child 遮挡.如果我们强行使用bringToFront(),就会发现顺序会被改变,而且还有其他问题出现.
其实在ViewGroup 绘制各个child 的时候是有一个顺序的,正常情况下就是按照GridView  各个child 从左到右,从上到下的顺序来绘制的.
当时这个顺序是可以改变的.
这其中涉及到2个ViewGroup关键方法:

protected int getChildDrawingOrder(int childCount, int i) {
        return i;
 }

protected void setChildrenDrawingOrderEnabled(boolean enabled) {
        setBooleanFlag(FLAG_USE_CHILD_DRAWING_ORDER, enabled);
}

如果要把选择的child View 放大,并显示在最上方不被其他view 遮挡.我们就需要修改绘制顺序.也就是重写getChildDrawingOrder()方法. 同时也要设置
setChildrenDrawingOrderEnabled(true); 来确保绘制时更新之后的顺序是有效的.
ViewGroup 的dispatchDraw方法(删除部分不需要看的代码了)

@Override
    protected void dispatchDraw(Canvas canvas) {
        boolean usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode);
        final int childrenCount = mChildrenCount;
        final View[] children = mChildren;
        int flags = mGroupFlags;

        //.....
        boolean more = false;
        final long drawingTime = getDrawingTime();

        if (usingRenderNodeProperties) canvas.insertReorderBarrier();
        final int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
        int transientIndex = transientCount != 0 ? 0 : -1;
        // Only use the preordered list if not HW accelerated, since the HW pipeline will do the
        // draw reordering internally
        final ArrayList<View> preorderedList = usingRenderNodeProperties
                ? null : buildOrderedChildList();
        final boolean customOrder = preorderedList == null
                && isChildrenDrawingOrderEnabled();
        for (int i = 0; i < childrenCount; i++) {
            while (transientIndex >= 0 && mTransientIndices.get(transientIndex) == i) {
                final View transientChild = mTransientViews.get(transientIndex);
                if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
                        transientChild.getAnimation() != null) {
                    more |= drawChild(canvas, transientChild, drawingTime);
                }
                transientIndex++;
                if (transientIndex >= transientCount) {
                    transientIndex = -1;
                }
            }
            int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
            final View child = (preorderedList == null)
                    ? children[childIndex] : preorderedList.get(childIndex);
            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
                more |= drawChild(canvas, child, drawingTime);
            }
        }
        while (transientIndex >= 0) {
            // there may be additional transient views after the normal views
            final View transientChild = mTransientViews.get(transientIndex);
            if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
                    transientChild.getAnimation() != null) {
                more |= drawChild(canvas, transientChild, drawingTime);
            }
            transientIndex++;
            if (transientIndex >= transientCount) {
                break;
            }
        }
        if (preorderedList != null) preorderedList.clear();

        // Draw any disappearing views that have animations
        if (mDisappearingChildren != null) {
            final ArrayList<View> disappearingChildren = mDisappearingChildren;
            final int disappearingCount = disappearingChildren.size() - 1;
            // Go backwards -- we may delete as animations finish
            for (int i = disappearingCount; i >= 0; i--) {
                final View child = disappearingChildren.get(i);
                more |= drawChild(canvas, child, drawingTime);
            }
        }
        if (usingRenderNodeProperties) canvas.insertInorderBarrier();

       
       //.....
    }

从上面代码可以看到getChildDrawingOrder 和setChildrenDrawingOrderEnabled 的作用了.
ViewGroup 的buildOrderedChildList方法

/**
     * Populates (and returns) mPreSortedChildren with a pre-ordered list of the View's children,
     * sorted first by Z, then by child drawing order (if applicable). This list must be cleared
     * after use to avoid leaking child Views.
     *
     * Uses a stable, insertion sort which is commonly O(n) for ViewGroups with very few elevated
     * children.
     */
    ArrayList<View> buildOrderedChildList() {
        final int count = mChildrenCount;
        if (count <= 1 || !hasChildWithZ()) return null;

        if (mPreSortedChildren == null) {
            mPreSortedChildren = new ArrayList<View>(count);
        } else {
            mPreSortedChildren.ensureCapacity(count);
        }

        final boolean useCustomOrder = isChildrenDrawingOrderEnabled();
        for (int i = 0; i < mChildrenCount; i++) {
            // add next child (in child order) to end of list
            int childIndex = useCustomOrder ? getChildDrawingOrder(mChildrenCount, i) : i;
            View nextChild = mChildren[childIndex];
            float currentZ = nextChild.getZ();

            // insert ahead of any Views with greater Z
            int insertIndex = i;
            while (insertIndex > 0 && mPreSortedChildren.get(insertIndex - 1).getZ() > currentZ) {
                insertIndex--;
            }
            mPreSortedChildren.add(insertIndex, nextChild);
        }
        return mPreSortedChildren;
    }

了解了基本的流程之后,下面贴一下一个简单的demo源码

public class MainActivity extends Activity {
	private Integer[] mImages = { R.drawable.p1,R.drawable.p2, R.drawable.p3,
			R.drawable.p4, R.drawable.p5,R.drawable.p6};
	GridAdapter mImageAdapter;
	
	private final String TAG = "zhangle";
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		final MyGridView gridview = (MyGridView) findViewById(R.id.gridview);
		mImageAdapter = new GridAdapter(this, mImages);
		gridview.setAdapter(mImageAdapter);
		gridview.setSelector(new StateListDrawable());//不要选中时的背景效果
		
		gridview.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				Log.d(TAG, "onItemClick position=" + position + " id=" +id);
				gridview.setCurrentPosition(position);
				setScaleAnimation(view);
				
			}
		});
	}
	
	private AnimationSet manimationSet;

	public void setScaleAnimation(View view) {
		AnimationSet animationSet = new AnimationSet(true);
		if (manimationSet != null && manimationSet != animationSet) {
			manimationSet.setFillAfter(false);
			manimationSet.cancel();
		}
		// ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 2f, 1.0f,
		// 2f, 1, 0.5f, 1, 0.5f);
		Animation scaleAnimation = AnimationUtils.loadAnimation(this,
				R.anim.anim);
		animationSet.addAnimation(scaleAnimation);
		animationSet.setFillAfter(true);
		view.startAnimation(animationSet);
		manimationSet = animationSet;
	}
}

 

 

 

public class MyGridView extends GridView {
	private final String TAG = "zhangle";
	private int mCurrposition = 0;

	public MyGridView(Context context) {
		super(context);
	}

	public MyGridView(Context context, AttributeSet attrs) {
		super(context, attrs);
		setChildrenDrawingOrderEnabled(true);
	}

	public void setCurrentPosition(int pos) {
		this.mCurrposition = pos;
	}

	@Override
	protected void setChildrenDrawingOrderEnabled(boolean enabled) {
		super.setChildrenDrawingOrderEnabled(enabled);
	}

	@Override
	protected int getChildDrawingOrder(int childCount, int i) {
		//把第一个和最后一个的绘制顺序交换一下
		if (i == childCount - 1) {
			return mCurrposition;
		}
		if (i == mCurrposition) {
			return childCount - 1;
		}
		return super.getChildDrawingOrder(childCount, i);
	}
	
}

 

public class GridAdapter extends BaseAdapter {
	private final String TAG = "zhangle";
	
	private Context mContext;
	private int selected = -1;
	private Integer[] list;

	public GridAdapter(Context context, Integer[] list) {
		this.mContext = context;
		this.list = list;
	}

	@Override
	public int getCount() {
		return list.length;
	}

	@Override
	public Object getItem(int position) {
		return list[position];
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	public void setSelectPosition(int id) {
		selected = id;
		this.notifyDataSetChanged();
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ImageView imageView = new ImageView(mContext);
		imageView.setLayoutParams(new GridView.LayoutParams(300, 300));
		imageView.setImageResource(list[position]);
		imageView.setPadding(10, 10, 10, 10);
		imageView.setScaleType(ImageView.ScaleType.FIT_XY);
		// imageView.setBackgroundResource(R.drawable.grid_item_sele_style);
		Log.d(TAG, "getView selected=" + selected + " position=" +position);
		/*if (selected == position) {
			setScaleAnimation(imageView);
		}*/
		return imageView;
	}
	
}

以上就是主要的源码.

参考:http://blog.csdn.net/coderinchina/article/details/51344970

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值