AndroidTV开发2实现Item选中放大效果

        TV电视和机顶盒都有一个获得焦点时放大效果,这是很常见的,最近也在做盒子和TV开发,研究了一下,这里给出源码和效果,后面会给出具体分析和计算公式。

 

1.item获得焦点时放大倍数和事件处理:

/**
 * item获得焦点时调用
 *
 * @param itemView view
 */
private void focusStatus(View itemView,int position) {
    if (itemView == null) {
        return;
    }

    float scal;
    scal = 1.8f;

    if (Build.VERSION.SDK_INT >= 21) {
        //抬高Z轴
        ViewCompat.animate(itemView).scaleX(scal).scaleY(scal).translationZ(1.1f).start();
    } else {
        ViewCompat.animate(itemView).scaleX(scal).scaleY(scal).start();
        ViewGroup parent = (ViewGroup) itemView.getParent();
        parent.requestLayout();
        parent.invalidate();
    }
    onItemFocus(itemView);
}

2.item失去焦点的处理:

/**
 * item失去焦点时
 *
 * @param itemView item对应的View
 */
private void normalStatus(View itemView) {
    if (itemView == null) {
        return;
    }
    if (Build.VERSION.SDK_INT >= 21) {
        ViewCompat.animate(itemView).scaleX(1.0f).scaleY(1.0f).translationZ(0).start();
    } else {
        ViewCompat.animate(itemView).scaleX(1.0f).scaleY(1.0f).start();
        ViewGroup parent = (ViewGroup) itemView.getParent();
        parent.requestLayout();
        parent.invalidate();
    }
    onItemGetNormal(itemView);
}

3.GameListAdapter完整代码如下:

package com.example.tvrecyclerview.adapter;

import android.content.Context;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.RecyclerView;

import com.example.tvrecyclerview.R;
import com.example.tvrecyclerview.bean.GameListBean;
import com.example.tvrecyclerview.util.GlideUtils;

import java.util.List;

/**
 * @author: njb
 * @date: 2020/6/22 0022 0:54
 * @desc:
 */
public abstract class GameListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<GameListBean> mList;
    private Context mContext;
    private OnItemFocusChangeListener mOnFocusChangeListener;
    private OnItemClickListener mOnItemClickListener;
    private final LayoutInflater mLayoutInflater;

    public GameListAdapter(List<GameListBean> mList,Context context,OnItemClickListener onItemClickListener) {
        this.mList = mList;
        this.mContext = context;
        mLayoutInflater = LayoutInflater.from(mContext);
        this.mOnItemClickListener = onItemClickListener;
    }

    public void setData(List<GameListBean> gameListBeans) {
        this.mList = gameListBeans;
        notifyDataSetChanged();
    }


    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }

    public interface OnItemFocusChangeListener {
        void onItemFocusChange(View view, int position, boolean hasFocus);
    }


    public final void setOnItemClickListener(@Nullable OnItemClickListener listener) {
        mOnItemClickListener = listener;
    }

    public void setOnFocusChangeListener(@Nullable OnItemFocusChangeListener mOnFocusChangeListener) {
        this.mOnFocusChangeListener = mOnFocusChangeListener;
    }


    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = mLayoutInflater.inflate(R.layout.listview_item,parent, false);
        return new RecyclerViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) {
        final RecyclerViewHolder viewHolder = (RecyclerViewHolder) holder;
        viewHolder.tv.setText(mList.get(position).getGameName());
        GlideUtils.loadImg(mContext,mList.get(position).getImg(),viewHolder.iv);
        if (mOnItemClickListener != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mOnItemClickListener.onItemClick(v, position);

                }
            });
        }
        holder.itemView.setFocusable(true);
        holder.itemView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if(hasFocus){
                    focusStatus(v,holder.getAdapterPosition());
                }else {
                    normalStatus(v);
                }
            }
        });
        holder.itemView.setOnHoverListener(new View.OnHoverListener() {
            @Override
            public boolean onHover(View v, MotionEvent event) {
                int what =event.getAction();
                switch (what) {
                    case MotionEvent.ACTION_HOVER_ENTER:
                        RecyclerView recyclerView = (RecyclerView) holder.itemView.getParent();
                        int[] location = new int[2];
                        recyclerView.getLocationOnScreen(location);
                        int x = location[0];
//                            LogUtil.i("swj","GalleryAdapter.onHover.x="+x +",width = "+(recyclerView.getWidth()+x));
                        //为了防止滚动冲突,在滚动时候,获取焦点为了显示全,会回滚,这样会导致滚动停止
                        if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {
                            //当超出RecyclerView的边缘时不去响应滚动
                            if (event.getRawX() > recyclerView.getWidth() + x || event.getRawX() < x) {
                                return true;
                            }
                            //鼠标进入view,争取到焦点
                            v.requestFocusFromTouch();
                            v.requestFocus();
//                                LogUtil.i(this,"HomeTvAdapter.onHover.position:"+position);
                            focusStatus(v, holder.getAdapterPosition());
                        }
                        break;
                    case MotionEvent.ACTION_HOVER_MOVE:  //鼠标在view上移动
                        break;
                    case MotionEvent.ACTION_HOVER_EXIT:  //鼠标离开view
                        normalStatus(v);
                        break;
                }
                return false;
            }
        });

    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    private class RecyclerViewHolder extends RecyclerView.ViewHolder {
        TextView tv;
        ImageView iv;
        RecyclerViewHolder(View itemView) {
            super(itemView);
            tv = (TextView) itemView.findViewById(R.id.tv_name);
            iv = (ImageView) itemView.findViewById(R.id.iv_bg);
        }
    }

    /**
     * item获得焦点时调用
     *
     * @param itemView view
     */
    private void focusStatus(View itemView,int position) {
        if (itemView == null) {
            return;
        }

        float scal;
        scal = 1.8f;

        if (Build.VERSION.SDK_INT >= 21) {
            //抬高Z轴
            ViewCompat.animate(itemView).scaleX(scal).scaleY(scal).translationZ(1.1f).start();
        } else {
            ViewCompat.animate(itemView).scaleX(scal).scaleY(scal).start();
            ViewGroup parent = (ViewGroup) itemView.getParent();
            parent.requestLayout();
            parent.invalidate();
        }
        onItemFocus(itemView);
    }

    /**
     * 当item获得焦点时处理
     *
     * @param itemView itemView
     */
    protected abstract void onItemFocus(View itemView);

    /**
     * item失去焦点时
     *
     * @param itemView item对应的View
     */
    private void normalStatus(View itemView) {
        if (itemView == null) {
            return;
        }
        if (Build.VERSION.SDK_INT >= 21) {
            ViewCompat.animate(itemView).scaleX(1.0f).scaleY(1.0f).translationZ(0).start();
        } else {
            ViewCompat.animate(itemView).scaleX(1.0f).scaleY(1.0f).start();
            ViewGroup parent = (ViewGroup) itemView.getParent();
            parent.requestLayout();
            parent.invalidate();
        }
        onItemGetNormal(itemView);
    }

    /**
     * 当条目失去焦点时调用
     *
     * @param itemView 条目对应的View
     */
    protected abstract void onItemGetNormal(View itemView);



}

4.MainActivity代码:

package com.example.tvrecyclerview;

import android.graphics.Rect;
import android.os.Bundle;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.tvrecyclerview.adapter.GameListAdapter;
import com.example.tvrecyclerview.adapter.MyRecycleViewAdapter;
import com.example.tvrecyclerview.bean.GameListBean;
import com.example.tvrecyclerview.util.ScreenUtil;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements MyRecycleViewAdapter.OnItemClickListener,MyRecycleViewAdapter.OnItemFocusChangeListener {
    private MyRecycleViewAdapter adapter;
    private RecyclerView recyclerView, rvGameList;
    //标题
    private String[] titles = {"首页", "游戏", "教育", "生活", "娱乐", "新闻", "直播", "我的"};
    private GameListAdapter gameListAdapter;
    private List<GameListBean> gameListBeans;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initAdapter();
        initGameListAdapter();
    }

    private void initGameListAdapter() {
        setData();
        gameListAdapter = new GameListAdapter(gameListBeans, this, new GameListAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {

            }
        }) {
            @Override
            protected void onItemFocus(View itemView) {
                itemView.setSelected(true);
                View view = itemView.findViewById(R.id.iv_bg);
                view.setSelected(true);
            }

            @Override
            protected void onItemGetNormal(View itemView) {
                itemView.setSelected(true);
                View view = itemView.findViewById(R.id.iv_bg);
                view.setSelected(true);
            }
        };
        rvGameList.setLayoutManager(new GridLayoutManager(this,4));
        rvGameList.addItemDecoration(new RecyclerView.ItemDecoration() {
            @Override
            public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
                super.getItemOffsets(outRect, view, parent, state);
                outRect.top  = ScreenUtil.dp2px(MainActivity.this,20);
            }
        });
        rvGameList.setAdapter(gameListAdapter);
    }

    /**
     * 初始化view
     */
    private void initView() {
        recyclerView = findViewById(R.id.rv_tab);
        rvGameList = findViewById(R.id.rv_game_list);
    }

    /**
     * 初始化Adapter
     */
    private void initAdapter() {
        adapter = new MyRecycleViewAdapter(this, titles);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setAdapter(adapter);
        recyclerView.requestFocus();
        adapter.setOnFocusChangeListener(this);
        adapter.setOnItemClickListener(this);
    }

    @Override
    public void onItemClick(View view, int position) {
        updateData(titles[position]);
    }



    private void updateData(String title) {
        if (gameListBeans != null && gameListBeans.size() > 0) {
            gameListBeans.clear();
        }
        for (int i = 0; i < 10; i++) {
            GameListBean gameListBean = new GameListBean();
            gameListBean.setGameName(title);
            gameListBean.setImg("2");
            gameListBeans.add(gameListBean);

        }
        gameListAdapter.notifyDataSetChanged();
    }

    private void setData() {
        gameListBeans = new ArrayList<>();
        for (int i = 0; i < 6; i++) {
            GameListBean gameListBean = new GameListBean();
            gameListBean.setGameName("王者荣耀");
            gameListBean.setImg("2");
            gameListBeans.add(gameListBean);
        }
    }

    @Override
    public void onItemFocusChange(View view, int position, boolean hasFocus) {
    }
}

5.实现的效果图如下:

6.这里的数据都是模拟假数据,小伙伴们如需真实数据可以写一个WanAndroidTV版,最后项目的源码完整地址如下:

TvRecyclerView: TV项目,使用recyclerview实现标题切换和焦点效果

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RecyclerView是Android开发中常用的列表控件,它可以实现各种不同的布局方式和功能。其中,使用RecyclerView实现画廊效果,即被选中item居中放大,是一种常见的需求。 实现RecyclerView的画廊效果,需要借助LayoutManager和ItemDecoration这两个类来实现。首先,需要自定义一个继承自LinearLayoutManager的类,例如GalleryLayoutManager。在GalleryLayoutManager中,我们需要重写onLayoutChildren方法,以实现item的布局。在这个方法中,我们可以通过计算item的布局位置和大小,实现选中item放大和居中。 接下来,我们还需要自定义一个继承自RecyclerView.ItemDecoration的类,例如GalleryItemDecoration。在GalleryItemDecoration中,我们需要重写getItemOffsets方法,以实现item间的间距效果。 在RecyclerView的Adapter中,我们可以使用ViewHolder的方式来管理item的布局和数据。当某个item选中时,我们可以通过改变其布局参数,实现放大效果。同时,我们还可以通过RecyclerView.scrollToPosition方法,使被选中item居中显示。 最后,在Activity或Fragment中,我们可以通过初始化RecyclerView、设置LayoutManager、ItemDecoration和Adapter等步骤,实现RecyclerView的画廊效果。当用户滑动RecyclerView时,我们可以通过监听RecyclerView的滑动事件,确定被选中item,并将其居中放大。 总的来说,通过自定义LayoutManager、ItemDecoration和对RecyclerView的布局参数的处理,配合Adapter和Activity/Fragment的协调,我们可以实现RecyclerView的画廊效果,即被选中item居中放大。通过这种方式,可以增加用户体验和提升界面的美观程度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值