android 手势操作垂直滑动,Android-水平和垂直方向都可滑动的RecycleView

最近有点忙,项目进度跟的比较紧。最近需求那边让我们写一个左右和上下都可滑动的列表,用来展示多个Title的值。这里我把需求简化了一下。老规矩,先看图。

320c499da51d

在看到需求的时候,有在网上看看有没有别人造好的轮子,找是找到了,但是它是用HorizontalScrollView、ScrollView、ListView实现的,效果是有了,但是ListView没有复用了,导致我一次性加载800条数据时,界面卡顿,体验很不好。而且它的点击效果只能分别点击左边和右边,并不能点击的时候整个item都高亮。

所以,这里我就去研究了一下该怎么实现这个需求。

这里我封装了一个HRecycleView去继承RelativeLayout。

分为上下两部分

① TitleLayout

包括左边的"名称"(固定不可滑动),右边的"Title"(多个可滑动)

② Title的数据

使用的是RecyclerView

这里只要处理水平方向的手势滑动即可,所以,我们需要去拦截手势,使用scrollTo方法实现水平滚动。请看代码的详细注释。

/**

* Created by chawei on 2018/4/29.

*/

public class HRecyclerView extends RelativeLayout {

//头部title布局

private LinearLayout mRightTitleLayout;

//手指按下时的位置

private float mStartX = 0;

//滑动时和按下时的差值

private int mMoveOffsetX = 0;

//最大可滑动差值

private int mFixX = 0;

//左边标题集合

private String[] mLeftTextList;

//左边标题的宽度集合

private int[] mLeftTextWidthList;

//右边标题集合

private String[] mRightTitleList = new String[]{};

//右边标题的宽度集合

private int[] mRightTitleWidthList = null;

//展示数据时使用的RecycleView

private RecyclerView mRecyclerView;

//RecycleView的Adapter

private Object mAdapter;

//需要滑动的View集合

private ArrayList mMoveViewList = new ArrayList();

private Context context;

//右边可滑动的总宽度

private int mRightTotalWidth = 0;

//右边单个view的宽度

private int mRightItemWidth = 60;

//左边view的宽度

private int mLeftViewWidth = 80;

//左边view的高度

private int mLeftViewHeight=40;

//触发拦截手势的最小值

private int mTriggerMoveDis=30;

public HRecyclerView(Context context) {

this(context, null);

}

public HRecyclerView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public HRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

this.context = context;

}

private void initView() {

LinearLayout linearLayout = new LinearLayout(getContext());

linearLayout.setOrientation(LinearLayout.VERTICAL);

linearLayout.addView(createHeadLayout());

linearLayout.addView(createMoveRecyclerView());

addView(linearLayout, new LayoutParams(LayoutParams.MATCH_PARENT,

ViewGroup.LayoutParams.MATCH_PARENT));

}

/**

* 创建头部布局

* @return

*/

private View createHeadLayout() {

LinearLayout headLayout = new LinearLayout(getContext());

headLayout.setGravity(Gravity.CENTER);

LinearLayout leftLayout = new LinearLayout(getContext());

addListHeaderTextView(mLeftTextList[0], mLeftTextWidthList[0], leftLayout);

leftLayout.setGravity(Gravity.CENTER);

headLayout.addView(leftLayout, 0, new ViewGroup.LayoutParams(dip2px(context, mLeftViewWidth), dip2px(context, mLeftViewHeight)));

mRightTitleLayout = new LinearLayout(getContext());

for (int i = 0; i < mRightTitleList.length; i++) {

addListHeaderTextView(mRightTitleList[i], mRightTitleWidthList[i], mRightTitleLayout);

}

headLayout.addView(mRightTitleLayout);

return headLayout;

}

/**

* 创建数据展示布局

* @return

*/

private View createMoveRecyclerView() {

RelativeLayout linearLayout = new RelativeLayout(getContext());

mRecyclerView = new RecyclerView(getContext());

LinearLayoutManager layoutManager = new LinearLayoutManager(context);

layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

mRecyclerView.setLayoutManager(layoutManager);

if(null !=mAdapter){

if (mAdapter instanceof CommonAdapter) {

mRecyclerView.setAdapter((CommonAdapter) mAdapter);

mMoveViewList = ((CommonAdapter) mAdapter).getMoveViewList();

}

}

linearLayout.addView(mRecyclerView, new LayoutParams(LayoutParams.MATCH_PARENT,

LayoutParams.MATCH_PARENT));

return linearLayout;

}

/**

* 设置adapter

* @param adapter

*/

public void setAdapter(Object adapter) {

mAdapter = adapter;

initView();

}

/**

* 设置头部title单个布局

* @param headerName

* @param width

* @param leftLayout

* @return

*/

private TextView addListHeaderTextView(String headerName, int width, LinearLayout leftLayout) {

TextView textView = new TextView(getContext());

textView.setText(headerName);

textView.setGravity(Gravity.CENTER);

leftLayout.addView(textView, width, dip2px(context, 50));

return textView;

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

switch (ev.getAction()) {

case MotionEvent.ACTION_DOWN:

mStartX = ev.getX();

break;

case MotionEvent.ACTION_MOVE:

int offsetX = (int) Math.abs(ev.getX() - mStartX);

if (offsetX > mTriggerMoveDis) {//水平移动大于30触发拦截

return true;

} else {

return false;

}

}

return super.onInterceptTouchEvent(ev);

}

/**

* 右边可滑动的总宽度

* @return

*/

private int rightTitleTotalWidth() {

if (0 == mRightTotalWidth) {

for (int i = 0; i < mRightTitleWidthList.length; i++) {

mRightTotalWidth = mRightTotalWidth + mRightTitleWidthList[i];

}

}

return mRightTotalWidth;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

return true;

case MotionEvent.ACTION_MOVE:

int offsetX = (int) Math.abs(event.getX() - mStartX);

if (offsetX > 30) {

mMoveOffsetX = (int) (mStartX - event.getX() + mFixX);

if (0 > mMoveOffsetX) {

mMoveOffsetX = 0;

} else {

//当滑动大于最大宽度时,不在滑动(右边到头了)

if ((mRightTitleLayout.getWidth() + mMoveOffsetX) > rightTitleTotalWidth()) {

mMoveOffsetX = rightTitleTotalWidth() - mRightTitleLayout.getWidth();

}

}

//跟随手指向右滚动

mRightTitleLayout.scrollTo(mMoveOffsetX, 0);

if (null != mMoveViewList) {

for (int i = 0; i < mMoveViewList.size(); i++) {

//使每个item随着手指向右滚动

mMoveViewList.get(i).scrollTo(mMoveOffsetX, 0);

}

}

}

break;

case MotionEvent.ACTION_UP:

mFixX = mMoveOffsetX; //设置最大水平平移的宽度

break;

}

return super.onTouchEvent(event);

}

/**

* 列表头部数据

* @param headerListData

*/

public void setHeaderListData(String[] headerListData) {

mRightTitleList = headerListData;

mRightTitleWidthList = new int[headerListData.length];

for (int i = 0; i < headerListData.length; i++) {

mRightTitleWidthList[i] = dip2px(context, mRightItemWidth);

}

mLeftTextWidthList = new int[]{dip2px(context, mLeftViewWidth)};

mLeftTextList = new String[]{"名称"};

}

}

这里模拟了一次加载1W条数据,没有卡顿效果。

/**

* Created by chawei on 2018/4/29.

*/

public class CoinActivity extends AppCompatActivity {

private ArrayList mDataModels;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_stock_layout);

HRecyclerView hRecyclerView= (HRecyclerView) findViewById(R.id.id_hrecyclerview);

mDataModels = new ArrayList<>();

for(int i=0;i<10000;i++) {

CoinInfo coinInfo = new CoinInfo();

coinInfo.name = "USDT";

coinInfo.priceLast="20.0";

coinInfo.riseRate24="0.2";

coinInfo.vol24="10020";

coinInfo.close="22.2";

coinInfo.open="40.0";

coinInfo.bid="33.2";

coinInfo.ask="19.0";

coinInfo.amountPercent = "33.3%";

mDataModels.add(coinInfo);

}

hRecyclerView.setHeaderListData(getResources().getStringArray(R.array.right_title_name));

CoinAdapter adapter = new CoinAdapter(this, mDataModels, R.layout.item_layout, new CommonViewHolder.onItemCommonClickListener() {

@Override

public void onItemClickListener(int position) {

Toast.makeText(CoinActivity.this, "position--->"+position, Toast.LENGTH_SHORT).show();

}

@Override

public void onItemLongClickListener(int position) {

}

});

hRecyclerView.setAdapter(adapter);

}

}

这里封装了RecyclerView的通用Adapter和ViewHolder。所以如果要使用HRecyclerView的setAdapter就必须继承封装的通用Adapter。

CommonAdapter和CommonViewHolder请点击demo地址查看

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中,可以通过自定义RecyclerView的ItemAnimator来实现滑动ItemView变大的效果。 首先,我们需要创建一个类来继承自RecyclerView.ItemAnimator,该类将负责处理ItemView的动画效果。代码如下: ```java public class CustomItemAnimator extends RecyclerView.ItemAnimator { @Override public boolean animateRemove(RecyclerView.ViewHolder holder) { return false; } @Override public boolean animateAdd(RecyclerView.ViewHolder holder) { return false; } @Override public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { return false; } @Override public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop) { if (oldHolder != null) { // 缩小旧的ItemView AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(ObjectAnimator.ofFloat(oldHolder.itemView, "scaleX", 1f, 0.5f), ObjectAnimator.ofFloat(oldHolder.itemView, "scaleY", 1f, 0.5f)); animatorSet.setDuration(getChangeDuration()).start(); } if (newHolder != null) { // 放大新的ItemView AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(ObjectAnimator.ofFloat(newHolder.itemView, "scaleX", 0.5f, 1f), ObjectAnimator.ofFloat(newHolder.itemView, "scaleY", 0.5f, 1f)); animatorSet.setDuration(getChangeDuration()).start(); } return false; } @Override public void runPendingAnimations() { } @Override public void endAnimation(RecyclerView.ViewHolder item) { } @Override public void endAnimations() { } @Override public boolean isRunning() { return false; } } ``` 接下来,在使用RecyclerView的地方,需调用setItemAnimator方法将自定义的ItemAnimator设置给RecyclerView。代码如下: ```java RecyclerView recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setItemAnimator(new CustomItemAnimator()); ``` 这样,当RecyclerView中的ItemView发生变化时,就会执行我们自定义的动画效果了。其中,在animateChange方法中我们通过对新旧ItemView的scaleX和scaleY属性进行属性动画来实现滑动ItemView变大的效果。 希望能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值