文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android中怎么使用ListView实现滚轮动画效果

2023-05-31 00:38

关注

今天就跟大家聊聊有关Android中怎么使用ListView实现滚轮动画效果,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

   private float centerY = 0f;   @Override   public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {     //计算中点     centerY = getHeight()/2;     //判断中点的有效性     if(centerY <= 0){       return;     }     //开始对当前显示的View进行缩放     for(int i = 0; i < visibleItemCount; i++){       //获取item       View temp_view = getChildAt(i);       //计算item的中点Y坐标       float itemY = temp_view.getBottom()-(temp_view.getHeight()/2);       //计算离中点的距离       float distance = centerY;       if(itemY > centerY){         distance = itemY - centerY;       }else{         distance = centerY - itemY;       }       //根据距离进行缩放       temp_view.setScaleY(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));       temp_view.setScaleX(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));       //根据距离改变透明度       temp_view.setAlpha(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));     }   }

后面不想加demo了,所以直接上整个ListView的代码吧

 public class XuListView extends ListView implements AbsListView.OnScrollListener {   private static final String TAG = "XuListView";       private float centerY = 0f;    public XuListView(Context context, AttributeSet attrs) {     super(context, attrs);     //设置一个滚动监听     setOnScrollListener(this);   }    @Override   public void onScrollStateChanged(AbsListView view, int scrollState) {    }    @Override   public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {     //计算中点     centerY = getHeight()/2;     //判断中点的有效性     if(centerY <= 0){       return;     }     //开始对当前显示的View进行缩放     for(int i = 0; i < visibleItemCount; i++){       //获取item       View temp_view = getChildAt(i);       //计算item的中点Y坐标       float itemY = temp_view.getBottom()-(temp_view.getHeight()/2);       //计算离中点的距离       float distance = centerY;       if(itemY > centerY){         distance = itemY - centerY;       }else{         distance = centerY - itemY;       }       //根据距离进行缩放       temp_view.setScaleY(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));       temp_view.setScaleX(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));       //根据距离改变透明度       temp_view.setAlpha(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));     }   } }

这样基本就实现了我们想要的效果了

Android中怎么使用ListView实现滚轮动画效果

但是现在有一个问题,就是第一个item和最后一个item无法滚动到中间从而放大突出显示。对此我暂时想了两个方法去解决:1、在头尾各种添加一些空白的item,使我们需要显示的数据都可以滚动到最中间。(我现在就是这么做的);2、使整个列表实现循环滚动。

添加空白的item的话,我是通过修改adapter去实现的。数据源是一个数组,我在数组前面和后面各加一些特殊的数据,adapter实现getview的时候,如果发现当前item的数据是特殊数据,那么item就变透明,从而实现了我们原本要显示的数据都可以被滚动最中间;

先从数据源下手,从头尾填充特殊的数据

public class MainActivity extends AppCompatActivity {   XuListView mLisetview;   MyAdapter adapter;   ArrayList<String> nos = new ArrayList<String>();   @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);          mLisetview = (XuListView) findViewById(R.id.list_test);      ArrayList<String> temp = new ArrayList<String>();     for(int i = 0;i<10;i++){       temp.add(i+"");     }     adapter = new MyAdapter(this,temp);     mLisetview.setAdapter(adapter);     resetitem(mLisetview);   }       private void resetitem(ListView listview) {      if(listview == null){       return;     }     //获取屏幕高度     WindowManager wm =getWindowManager();     int displayheight = wm.getDefaultDisplay().getHeight();     //计算一个item的高度     int itemhight = 0;     if(adapter!=null){       View v=(View)adapter.getView(0, null, listview);       v.measure(           View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),           View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));       itemhight=v.getMeasuredHeight();     }     //根据Item的高度和屏幕的高度计算需要多少个item可以填满一半的屏幕     int newcount = ((displayheight/2)/itemhight);     //填充前面的空白item     for (int i = 1; i <= newcount; i++) {       nos.add("full");     }     //添加我们需要显示的数据     for(int i = 0;i<10;i++){       nos.add(i+"");     }     //填充后面的空白item     for (int i = 1; i <= newcount; i++) {       nos.add("full");     }     //刷新数据     adapter.refreshData(nos);   } }

然后adapter里面对头尾的特殊数据进行识别,将item变为透明的。

public class MyAdapter extends BaseAdapter {    ArrayList<String> nos = new ArrayList<String>();   private Context context;    public MyAdapter(Context context, ArrayList<String> nos){     this.context = context;     this.nos = nos;   }   public void refreshData(ArrayList<String> nos) {     this.nos = nos;     notifyDataSetChanged();   }   @Override   public int getCount() {     return nos.size();   }    @Override   public Object getItem(int position) {     return nos.get(position);   }    @Override   public long getItemId(int position) {     return position;   }    @Override   public View getView(int position, View convertView, ViewGroup parent) {     ViewHolder holder = null;     if (convertView == null) {     // 如果是第一次显示该页面(要记得保存到viewholder中供下次直接从缓存中调用)       holder = new ViewHolder();       convertView = LayoutInflater.from(context).inflate(R.layout.item_test, null);       holder.tv_no = (TextView) convertView.findViewById(R.id.tv_no);       convertView.setTag(holder);     } else {       holder = (ViewHolder) convertView.getTag();     }     holder.tv_no.setText(nos.get(position));     if(nos.get(position).equals("full")){       convertView.setVisibility(View.INVISIBLE);     }else{       convertView.setVisibility(View.VISIBLE);     }     return convertView;   }         private class ViewHolder {     TextView tv_no;   } }

 这样我们就实现可以第一种解决方法

Android中怎么使用ListView实现滚轮动画效果

第二种方法,就是让整个ListView实现循环滚动,实现的方式有很多,大家可以自行百度,我这里就通过修改adapter的getCount方法去实现,就是在getCount方法return一个很大的值,getView获取数据的时候要模原本的数组大小,不然数组就越界了。然后ListView滚动到最中间,这样就实现伪循环滚动了

public class MainActivity extends AppCompatActivity {   XuListView mLisetview;   MyAdapter adapter;   ArrayList<String> nos = new ArrayList<String>();   @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);      mLisetview = (XuListView) findViewById(R.id.list_test);      ArrayList<String> temp = new ArrayList<String>();     for(int i = 0;i<10;i++){       temp.add(i+"");     }     adapter = new MyAdapter(this,temp);     mLisetview.setAdapter(adapter);     //滚动到中间     mLisetview.setSelection(adapter.getCount()/2);   }  }
 public class MyAdapter extends BaseAdapter {    ArrayList<String> nos = new ArrayList<String>();   private Context context;    public MyAdapter(Context context, ArrayList<String> nos){     this.context = context;     this.nos = nos;   }   @Override   public int getCount() {     return Integer.MAX_VALUE;   }    @Override   public Object getItem(int position) {     return nos.get(position);   }    @Override   public long getItemId(int position) {     return position;   }    @Override   public View getView(int position, View convertView, ViewGroup parent) {     ViewHolder holder = null;     if (convertView == null) {     // 如果是第一次显示该页面(要记得保存到viewholder中供下次直接从缓存中调用)       holder = new ViewHolder();       convertView = LayoutInflater.from(context).inflate(R.layout.item_test, null);       holder.tv_no = (TextView) convertView.findViewById(R.id.tv_no);       convertView.setTag(holder);     } else {       holder = (ViewHolder) convertView.getTag();     }     holder.tv_no.setText(nos.get(position%nos.size()));     return convertView;   }     private class ViewHolder {     TextView tv_no;   } }

这样我们就实现了使列表进行循环滚动,从而达到每个item都可以滚动到中间突出显示的效果了

Android中怎么使用ListView实现滚轮动画效果

既然我们把动画效果都做出来了,那么也可以直接做成一个滚轮选择器,只需要加多两步:1、把最靠近中间的item滚动到中间;2、把中间的item的序号通过一个接口返回出去。 我就直接贴代码吧,反正也不难。

把最靠近中间的item滚动到中间的实现我是这么做的:首先决定好整个ListView可视的的item数量是多少,必须是奇数,这样才能只有一个item处于正中间,然后根据ListView的高度计算出每个item符合要求的高度,然后更改现有的item的高度,同时对内容进行缩放(不缩放内容单纯高度变小的话布局就乱了)。最后我们利用smoothScrollToPosition方法回正可视item中的第一个item,就实现了将最中间的item回滚到最中间的效果了。因为可视的item我们是根据ListView的高度去计算item的高度的,所有的可视item刚好铺满ListView,所以只要顶部那个回正了,其他的item也会回正。所以我们可以重写一下OnScrollListener的onScrollStateChanged方法,每次滚动结束就执行一次回滚

 private int mVisibleItemCount = -1;  private float olditemheight = 0;  private float newitemheight = -1;   public void reSetItemHeight() {   for (int i = 0; i < getChildCount(); i++) {     //获取item     View temp_view = getChildAt(i);     //设置item的高度     ViewGroup.LayoutParams lp = temp_view.getLayoutParams();     lp.height = (int) newitemheight;     temp_view.setLayoutParams(lp);      //缩放内容 我的item的内容用一个LinearLayout包了起来 所以直接缩放LinearLayout     LinearLayout item_ll_value = (LinearLayout) temp_view.findViewById(R.id.item_ll_value);     item_ll_value.setScaleY((newitemheight / olditemheight) < 0 ? 0 : (newitemheight / olditemheight));     item_ll_value.setScaleX((newitemheight / olditemheight) < 0 ? 0 : (newitemheight / olditemheight));   } }  private void getNewItemHeight() {   //先把旧的item存起来   olditemheight = getChildAt(0).getHeight();   //计算新的高度   newitemheight = getHeight() / mVisibleItemCount;   if ((getHeight() / mVisibleItemCount) % newitemheight > 0) {     //除不尽的情况下把余数分给各个item,暂时发现分一次余数就够了,如果效果不理想就做个递归多分几次     float remainder = (getHeight() / mVisibleItemCount) % newitemheight;     newitemheight = remainder / mVisibleItemCount;    } }  @Override public void onScrollStateChanged(AbsListView view, int scrollState) {    //滚动结束之后开始回滚item   if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && mVisibleItemCount != -1) {     //使离中间最近的item回滚到中点位置     smoothScrollToPosition(getFirstVisiblePosition());   }  }

实现了把最靠近中间的item滚动到中间,那么选择的item就是滚动结束后处于最中间的item。对此我们需要再次重写一下OnScrollListener的onScrollStateChanged方法。每次滚动结束后,取可视item中的第一个item的序号加上我们之前设置的可视item数的一半(舍去小数部分)就是最中间的item的序号了,也是当前选择项的序号。

   private onSelectionChangeLisenter selectionChangeLisenter;          public void setSelectionChangeLisenter(onSelectionChangeLisenter selectionChangeLisenter) {     this.selectionChangeLisenter = selectionChangeLisenter;   }      @Override   public void onScrollStateChanged(AbsListView view, int scrollState) {       //滚动结束之后开始正常回滚item并记录最中间的item为选中项 (必须设置可视项,ListView才会改为选择器模式)     if( scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && mVisibleItemCount != -1){       //使离中间最近的item回滚到中点位置       smoothScrollToPosition(getFirstVisiblePosition());       //计算当前选中项的序号       int nowPosition = getFirstVisiblePosition() + mVisibleItemCount/2;       //把当前选中项的序号存起来并通过listener回调出去       if(selectionChangeLisenter != null && nowPosition != curPosition){         curPosition = nowPosition;         selectionChangeLisenter.onSelectionChange(curPosition);       }     }    }

此处我是使用了一个接口去,用以实时把最新的数据返回出去

 public interface onSelectionChangeLisenter {   void onSelectionChange(int position); }

使用这个滚轮选择器的方法也非常简单,除了跟正常的ListView初始化和绑定adapter之外,只需要额外调用两个方法就行了

//设置ListView的可视item数(必须是奇数)     mLisetview.setVisibleItemCount(3);
//设置监听者监听选中项的变化     mLisetview.setSelectionChangeLisenter(new onSelectionChangeLisenter() {       @Override       public void onSelectionChange(final int position) {         mHandler.post(new Runnable() {           @Override           public void run() {             Toast.makeText(MainActivity.this,"选择项发生变化 当前选中序号:"+(temp.get(position)),Toast.LENGTH_SHORT).show();           }         });       }     });

这样我们就实现滚轮数字选择器的效果了

Android中怎么使用ListView实现滚轮动画效果

现在贴下整个滚轮选择器的完整代码

 public class XuListView extends ListView implements AbsListView.OnScrollListener {   private static final String TAG = "XuListView";       private float centerY = 0f;      private int mVisibleItemCount = -1;      private float olditemheight = 0;      private float newitemheight = -1;      private onSelectionChangeLisenter selectionChangeLisenter;      private int curPosition = -1;    public XuListView(Context context, AttributeSet attrs) {     super(context, attrs);     //设置一个滚动监听     setOnScrollListener(this);   }       public void setSelectionChangeLisenter(onSelectionChangeLisenter selectionChangeLisenter) {     this.selectionChangeLisenter = selectionChangeLisenter;   }       public boolean setVisibleItemCount(int count){     if(count % 2 == 0){       return false;     }else{       mVisibleItemCount = count;       return true;     }    }       @Override   public void onWindowFocusChanged(boolean hasWindowFocus) {     super.onWindowFocusChanged(hasWindowFocus);     if(mVisibleItemCount != -1){       getNewItemHeight();       reSetItemHeight();     }   }       public void reSetItemHeight(){     for(int i = 0; i < getChildCount(); i++){       //获取item       View temp_view = getChildAt(i);       //设置item的高度       ViewGroup.LayoutParams lp = temp_view.getLayoutParams();       lp.height = (int)newitemheight;       temp_view.setLayoutParams(lp);        //缩放内容 我的item的内容用一个LinearLayout包了起来 所以直接缩放LinearLayout       LinearLayout item_ll_value = (LinearLayout)temp_view.findViewById(R.id.item_ll_value);       item_ll_value.setScaleY((newitemheight / olditemheight) < 0 ? 0 : (newitemheight / olditemheight));       item_ll_value.setScaleX((newitemheight / olditemheight) < 0 ? 0 : (newitemheight / olditemheight));     }   }        private void getNewItemHeight(){     //先把旧的item存起来     olditemheight = getChildAt(0).getHeight();     //计算新的高度     newitemheight = getHeight()/mVisibleItemCount;     if((getHeight()/mVisibleItemCount) % newitemheight > 0){       //除不尽的情况下把余数分给各个item,暂时发现分一次余数就够了,如果效果不理想就做个递归多分几次       float remainder = (getHeight()/mVisibleItemCount) % newitemheight;       newitemheight = remainder/mVisibleItemCount;     }   }      @Override   public void onScrollStateChanged(AbsListView view, int scrollState) {       //滚动结束之后开始正常回滚item并记录最中间的item为选中项 (必须设置可视项,ListView才会改为选择器模式)     if( scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && mVisibleItemCount != -1){       //使离中间最近的item回滚到中点位置       smoothScrollToPosition(getFirstVisiblePosition());       //计算当前选中项的序号       int nowPosition = getFirstVisiblePosition() + mVisibleItemCount/2;       //把当前选中项的序号存起来并通过listener回调出去       if(selectionChangeLisenter != null && nowPosition != curPosition){         curPosition = nowPosition;         selectionChangeLisenter.onSelectionChange(curPosition);       }     }        }    @Override   public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {     //计算中点     centerY = getHeight()/2;     //判断中点的有效性     if(centerY <= 0){       return;     }     //开始对当前显示的View进行缩放     for(int i = 0; i < visibleItemCount; i++){       //获取item       View temp_view = getChildAt(i);       //计算item的中点Y坐标       float itemY = temp_view.getBottom()-(temp_view.getHeight()/2);       //计算离中点的距离       float distance = centerY;       if(itemY > centerY){         distance = itemY - centerY;       }else{         distance = centerY - itemY;       }        //根据距离进行缩放       temp_view.setScaleY(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));       temp_view.setScaleX(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));       //根据距离改变透明度       temp_view.setAlpha(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));     }   }  }

看完上述内容,你们对Android中怎么使用ListView实现滚轮动画效果有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网行业资讯频道,感谢大家的支持。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯