1.在RecyclerView实现GridView类似效果时,每个item的大小尺寸是随着传入spanCount的数值大小改变而改变的。所以获取item是要实现动态获取。
mRecyclerView.setLayoutManager(new GridLayoutManager(this, VERTICALCOUNT));
因此在MyAdapter类设置一个接口回调来传入所要知道对应position的item。
if (mOnItemClickLitener!=null){ //设置回调 holder.mItem_fl.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int layoutPosition = holder.getLayoutPosition(); mOnItemClickLitener.onItemClick(holder.mItem_fl,layoutPosition); } }); }
2.设置OnItemClickLitener的方法时要注意是要传入一个ViewGroup,因为只有ViewGroup中才有getChidAt()这个方法获取子view,而如果传入的是View则没有这个方法从而无法获取item中的子类进行设置对应的coverItem的数据。
public interface OnItemClickLitener{ //传入ViewGroup能在获取的时候用其特性获取子view void onItemClick(ViewGroup view, int position); }
mChildAt = (TextView) view.getChildAt(0); //从viewgroup获取子view mItemTvCover.setText(mChildAt.getText());
3.接下来是copy一份与item一模一样的布局,把这个布局添加到根布局中,运用ViewGroup中的addView()添加。
mAddView = (LinearLayout) LayoutInflater.from(MainActivity.this).inflate(R.layout.addview, mLl, false); mLl.addView(mAddView);
4.获取item的宽高值把coverItem设置为item的宽高:
int measuredWidth = view.getMeasuredWidth(); int measuredHeight = view.getMeasuredHeight(); setItemCoverSize(measuredWidth, measuredHeight); private void setItemCoverSize(int measuredWidth, int measuredHeight) { ViewGroup.LayoutParams layoutParams = mItem_fl_cover.getLayoutParams(); layoutParams.width = measuredWidth; layoutParams.height = measuredHeight; mItem_fl_cover.setLayoutParams(layoutParams); }
5.获取item的相对屏幕原点的XY坐标,获取coverItem相对于屏幕原点的XY坐标,获取RecycleView的宽高值,item的宽高值。
//获取item的相对原点位置 int[] outlocaton = new int[2]; view.getLocationOnScreen(outlocaton); int itemXLoaction = outlocaton[0]; int itemYtLoacton = outlocaton[1]; //获取coverItem相对原点位置 int[] coverLocaton = new int[2]; mItem_fl_cover.getLocationOnScreen(coverLocaton); int coverItemXLoaction = coverLocaton[0]; int coverItemYLoaction = coverLocaton[1]; //获取recycleview的宽高 int measuredWidth1 = mRecyclerView.getMeasuredWidth(); int measuredHeight1 = mRecyclerView.getMeasuredHeight();
6.将控件对应的位置传入setItemAnimator进行动画设置。
setItemAnimator(itemXLoaction, y); 在这个过程中遇到很多的问题,尤其是Android中的坐标系的问题,设置错了坐标设置的动画会莫名的跑出屏幕可见的范围之外。
下面是代码:
1.activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RecycleViewDemo" android:textSize="20dp"/> <android.support.v7.widget.RecyclerView android:id="@+id/activity_recycleview" android:divider="#ffff0000" android:dividerHeight="10dp" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.v7.widget.RecyclerView> </LinearLayout> 2.item.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#44ff0000" android:id="@+id/item_fl" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_gravity="center" android:id="@+id/item_tv" android:layout_width="50dp" android:layout_height="50dp" android:gravity="center" android:text="标签" android:textSize="20dip"/> <ImageView android:id="@+id/item_iv" android:src="@mipmap/ic_launcher" android:layout_gravity="center" android:layout_width="50dp" android:layout_height="50dp"/> </LinearLayout>
3.itemcover.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#8888" android:id="@+id/item_fl_cover" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_gravity="center" android:id="@+id/item_tv_cover" android:layout_width="50dp" android:layout_height="50dp" android:gravity="center" android:text="标签" android:textSize="20dip"/> <ImageView android:id="@+id/item_iv_cover" android:src="@mipmap/ic_launcher" android:layout_gravity="center" android:layout_width="50dp" android:layout_height="50dp"/> </LinearLayout> 4.MainActivity.java:
package com.example.foreveross.addviewdemo; import android.graphics.Rect; import android.net.Uri; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.TranslateAnimation; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.appindexing.Action; import com.google.android.gms.appindexing.AppIndex; import com.google.android.gms.common.api.GoogleApiClient; public class MainActivity extends AppCompatActivity { private static final int VERTICALCOUNT = 4; private String[] mDatas = new String[]{"春炮竹", "福炮竹", "福字", "新年快乐", "灯笼", "狮子头", "耍狮子", "招财猫", "恭喜发财", "点燃的炮竹", "剪纸", "春字"}; private RecyclerView mRecyclerView; private MyAdapter mMyAdapter; private LinearLayout mLl; private LinearLayout mAddView; private TextView mItemTvCover; private LinearLayout mItem_fl_cover; private GoogleApiClient mClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); initEvent(); } private void initEvent() { mMyAdapter.setOnItemClickLitener(new MyAdapter.OnItemClickLitener() { private TextView mChildAt; @Override public void onItemClick(ViewGroup view, int position) { mItem_fl_cover.setVisibility(View.VISIBLE); //获取item的相对原点位置 int[] outlocaton = new int[2]; view.getLocationOnScreen(outlocaton); int itemXLoaction = outlocaton[0]; int itemYtLoacton = outlocaton[1]; //获取coverItem相对原点位置 int[] coverLocaton = new int[2]; mItem_fl_cover.getLocationOnScreen(coverLocaton); int coverItemXLoaction = coverLocaton[0]; int coverItemYLoaction = coverLocaton[1]; //获取recycleview的宽高 int measuredWidth1 = mRecyclerView.getMeasuredWidth(); int measuredHeight1 = mRecyclerView.getMeasuredHeight(); Toast.makeText(MainActivity.this, "y值为:" + itemXLoaction, Toast.LENGTH_SHORT).show(); // Toast.makeText(MainActivity.this, "itemXLoaction:"+itemXLoaction // + "itemYtLoacton:" + itemYtLoacton // +"coverItemXLoaction:"+coverItemXLoaction // +"coverItemYLoaction:"+coverItemYLoaction, Toast.LENGTH_SHORT).show(); int measuredWidth = view.getMeasuredWidth(); int measuredHeight = view.getMeasuredHeight(); //计算item的行数 int i = mDatas.length / VERTICALCOUNT; //点击的item的Y值与itemcover的Y之间的差值 int y = -measuredHeight1+itemYtLoacton-measuredHeight ; //设置item的动画开始的Y位置 //获取item的尺寸 setItemCoverSize(measuredWidth, measuredHeight); mChildAt = (TextView) view.getChildAt(0); //从viewgroup获取子view mItemTvCover.setText(mChildAt.getText()); setItemAnimator(itemXLoaction, y); } }); } private void setItemCoverSize(int measuredWidth, int measuredHeight) { ViewGroup.LayoutParams layoutParams = mItem_fl_cover.getLayoutParams(); layoutParams.width = measuredWidth; layoutParams.height = measuredHeight; mItem_fl_cover.setLayoutParams(layoutParams); } private void initData() { } private void initView() { mLl = (LinearLayout) findViewById(R.id.ll); mRecyclerView = (RecyclerView) findViewById(R.id.activity_recycleview); // mRecyclerView.addItemDecoration(new SpaceItemDecoration(R.dimen.space)); //增加item的装饰 mRecyclerView.setLayoutManager(new GridLayoutManager(this, VERTICALCOUNT)); mMyAdapter = new MyAdapter(this, mDatas); mRecyclerView.setAdapter(mMyAdapter); //添加一个覆盖的view mAddView = (LinearLayout) LayoutInflater.from(MainActivity.this).inflate(R.layout.addview, mLl, false); mLl.addView(mAddView); mItemTvCover = (TextView) mLl.findViewById(R.id.item_tv_cover); mItem_fl_cover = (LinearLayout) mLl.findViewById(R.id.item_fl_cover); } private void setItemAnimator(float x, float y) { // Toast.makeText(MainActivity.this,"动画设置的x:"+x+"动画设置的Y:"+y,Toast.LENGTH_SHORT).show(); TranslateAnimation translateAnimaton = new TranslateAnimation(x, x, y, y - 1000); AnimationSet animationSet = new AnimationSet(true); AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0); animationSet.addAnimation(translateAnimaton); animationSet.addAnimation(alphaAnimation); animationSet.setDuration(5000); mItem_fl_cover.setAnimation(animationSet); animationSet.start(); animationSet.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { //动画结束时隐藏framelayout mItem_fl_cover.setVisibility(View.GONE); } @Override public void onAnimationRepeat(Animation animation) { } }); } /** * 给item设置装饰 */ public class SpaceItemDecoration extends RecyclerView.ItemDecoration { int spaceSize; public SpaceItemDecoration(int spaceSize) { this.spaceSize = spaceSize; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (parent.getChildPosition(view) != 0) { outRect.left = spaceSize; outRect.bottom = spaceSize; outRect.top = spaceSize; outRect.right = spaceSize; } } } } 5.MyAdapter.java: package com.example.foreveross.addviewdemo; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; /** * Created by Foreveross on 2017/4/3. */ public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { Context mContext; String[] mData; public MyAdapter(Context context, String[] data) { this.mContext = context; this.mData = data; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { MyViewHolder myViewHolder = new MyViewHolder(LayoutInflater.from(mContext) .inflate(R.layout.recycleview, parent, false)); return myViewHolder; } @Override public void onBindViewHolder(final MyViewHolder holder, int position) { holder.mItem_tv.setText(mData[position]); if (mOnItemClickLitener!=null){ //设置回调 holder.mItem_fl.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int layoutPosition = holder.getLayoutPosition(); mOnItemClickLitener.onItemClick(holder.mItem_fl,layoutPosition); } }); } } @Override public int getItemCount() { return mData.length; } //创建一个viewholder class MyViewHolder extends RecyclerView.ViewHolder { private final LinearLayout mItem_fl; private final TextView mItem_tv; public MyViewHolder(View view) { super(view); mItem_tv = (TextView) view.findViewById(R.id.item_tv); mItem_fl = (LinearLayout) view.findViewById(R.id.item_fl); } } public OnItemClickLitener mOnItemClickLitener; public interface OnItemClickLitener{ //传入ViewGroup能在获取的时候用其特性获取子view void onItemClick(ViewGroup view, int position); } public void setOnItemClickLitener(OnItemClickLitener on){ this.mOnItemClickLitener=on; } }
代码地址为:http://dl.download.csdn.net/down11/20170404/64060f26830e17abdc6e458f4ba964a2.rar?response-content-disposition=attachment;filename="AddViewDemo.rar"&OSSAccessKeyId=9q6nvzoJGowBj4q1&Expires=1491301209&Signature=i/HRiBo8qxSdf90YLlG9uQ8GTes=
Android坐标系全解:http://blog.csdn.net/yanbober/article/details/50419117
总结:
1.Android的坐标原点是在屏幕的左上角,以这个点向右为X的正方向,向下为Y的正方向。
2.view.getLocationOnScreen()获取的是view的相对于屏幕的坐标原点,
view.getLocationInWindow()获取的是相对父控件的坐标。
3.getX()返回值为:getLeft()+getTranslationX();
getLeft():是view自身左边到父控件左边的距离;
getWidth():layout后有效返回值是mRight-mLeft;
getMeasuredWidth():返回measure过程得到的mMeasuredWidth值。
4.TranslateAnimation动画中的fromXDelta是动画开始相对于自身的X的坐标位置,fromXDelta是动画结束时相对自身的X的坐标位置。
5.在ViewGroup中添加view是addView()方法,设置view的宽高是先获取view.getLayoutParams()的参数设置之后再添加宽高,最后在view.setLayoutParams(layoutParams)。