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%3Bfilename%3D%22AddViewDemo.rar%22&OSSAccessKeyId=9q6nvzoJGowBj4q1&Expires=1491301209&Signature=i%2FHRiBo8qxSdf90YLlG9uQ8GTes%3D
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)。