Android使用ListView实现滚轮的动画效果实例

之前收到一个需求,需要把一个数据展示列表页面做成像滚轮那样的动画效果:中间最大然后向上下两端逐渐缩小。我想了想iOS那边自带滚轮组件,安卓得自己去实现,目前网上仿ios的滚轮组件的也有一些,但是感觉不适合我,我的要求没那么复杂,于是决定自己动手去实现一下。

动手前先分析一下应该怎么做,归根到底只是要实现缩放效果,由中间向两边变小,当一个item越接近中间就放大,越远离中间就缩小。那么可以通过先获取ListView的中点,然后获取当前可视的所有item跟ListView的中点的垂直距离计算出一个比例,然后将item的大小根据这个比例进行缩放,各个item跟ListView的中点的垂直距离不同,计算出来的比例也就不同,然后每次滚动的时候都计算比例然后进行缩放,这样应该就能实现我们想要的效果了。

因为一开始我的列表展示就是用ListView做的,有其他效果在里面,也不方便换其他组件,所以依然还是用ListView实现就好了。由于我们是每次一滚动都要进行缩放,ListView有提供一个OnScrollListener,它的onScroll方法每次一开始滚动就会调用,所以我们选择重写它。当它被调用的时候,我们就开始获取ListView中点,然后开始计算每个item的距离进行缩放.

/**
  * 中点的Y坐标
  */
  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的代码吧

/**
 * 模仿滚轮动画缩放的ListView
 * Created by xu on 2017/3/3.
 */
public class XuListView extends ListView implements AbsListView.OnScrollListener {
  private static final String TAG = "XuListView"; 

  /**
   * 中点的Y坐标
   */
  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));
    }
  }
}

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

但是现在有一个问题,就是第一个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);
  } 

  /**
   * 在头尾填充透明的item数据
   */
  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;
  }
}

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

第二种方法,就是让整个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);
  } 

}
/**
 * Created by xu on 2017/6/27.
 */
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都可以滚动到中间突出显示的效果了

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

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

/**
 * 可视的item数
 */
private int mVisibleItemCount = -1;
/**
 * 没调整之前每个item的高度
 */
private float olditemheight = 0;
/**
 * 调整过后的每个item的高度
 */
private float newitemheight = -1; 

/**
 * 调整每个可视的item的高度 以及对内容进行缩放
 */
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));
  }
}
/**
 * 计算在给定的可视item数目下 每个item应该设置的高度
 * */
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);
      }
    } 

  }

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

/**
 * Created by xu on 2017/3/3.
 */
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();
          }
        });
      }
    });

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

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

/**
 * 模仿滚轮动画缩放的ListView
 * Created by xu on 2017/3/3.
 */
public class XuListView extends ListView implements AbsListView.OnScrollListener {
  private static final String TAG = "XuListView"; 

  /**
   * 中点的Y坐标
   */
  private float centerY = 0f;
  /**
   * 可视的item数
   */
  private int mVisibleItemCount = -1;
  /**
   * 没调整之前每个item的高度
   */
  private float olditemheight = 0;
  /**
   * 调整过后的每个item的高度
   */
  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;
  } 

  /**
   * 设置ListView的显示item数
   * @param count :必须是奇数  如果为-1 则表示只是使用动画效果的普通ListView
   */
  public boolean setVisibleItemCount(int count){
    if(count % 2 == 0){
      return false;
    }else{
      mVisibleItemCount = count;
      return true;
    } 

  } 

  /**
   * 在这里第一次调整item高度
   */
  @Override
  public void onWindowFocusChanged(boolean hasWindowFocus) {
    super.onWindowFocusChanged(hasWindowFocus);
    if(mVisibleItemCount != -1){
      getNewItemHeight();
      reSetItemHeight();
    }
  } 

  /**
   * 调整每个可视的item的高度 以及对内容进行缩放
   */
  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));
    }
  } 

  /**
   * 计算在给定的可视item数目下 每个item应该设置的高度
   */
  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));
    }
  } 

}

注释很详细 相信小白看了也没什么难度。

滚轮效果的实现方式有很多,解决头尾两个item无法滚动到中间的方法也很多,我说的方法仅供参考,没有最好的方法,只有最符合自己的需求的方法。

demo下载地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android Adapter里面嵌套ListView实例详解

    Android Adapter里面嵌套ListView实例详解 前言: 可嵌套~但是显示需要特殊处理下~以下是处理方法 前几天因为项目的需要,要在一个ListView中放入另一个ListView,也即在一个ListView的每个ListItem中放入另外一个ListView.但刚开始的时候,会发现放入的小ListView会显示不完全,它的高度始终有问题.上网查了下,发现别人也有遇到这样的问题,而大多数人都不推荐这样的设计,因为默认情况下Android是禁止在ScrollView中放入另外的Scr

  • Android ListView中headerview的动态显示和隐藏的实现方法

    Android ListView中headerview的动态显示和隐藏的实现方法 1.动态设置headerview的方法 动态设置headerview有两个思路. 方法一 将header的布局写在list item的布局文件中,在adapter中通过判断position的值是否为0动态控制其显示或隐藏. 代码示例: item.xml布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout x

  • Android ListView实现ImageLoader图片加载的方法

    本文实例讲述了Android ListView实现ImageLoader图片加载的方法.分享给大家供大家参考,具体如下: 最近一直忙着做项目,今天也是忙里偷闲,想写篇博客来巩固下之前在应用中所用的知识.之前我们可能会也会肯定遇到了图片的异步加载问题,然而我们也可能会遇到图片二次或多次加载,这是ListView的特性造成的,具体原因不在这里讨论,又或者是OOM等问题.今天要讲的是一个开源框架Imageloader,个人觉得非常的好用. 该框架在github的地址.https://github.co

  • Android ListView滑动改变标题栏背景渐变效果

    先上ListView滑动改变标题栏背景渐变效果图,透明转变成不透明效果: 图1: 图2: 图3: 图4: 我用的是小米Note手机,状态栏高度是55px,后面会提到,这里先做个说明: 下面的内容包含了所有代码和一些测试数据: 代码: 代码很简单,也做了注释,这里就不废话了. 先来布局文件: activity的布局 activity_main_10 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/androi

  • 详解xamarin Android 实现ListView万能适配器

    详解xamarin Android 实现ListView万能适配器 早些时候接触xamarin Android 的列表,写了很多ListView的Adapter,建一个ListView就写一个Adapter,每一个Adapter里面还有去写一个ViewHolder的类来优化,自从看了hongyang博客的listview万能适配器的文章,学习良多,所以就写篇关于xamarin android ListView通用适配器的文章. 本章主要分为以下三点: 打造通用的ViewHolder优化ListV

  • Android 实现ListView的点击变色的实例

    Android 实现ListView的点击变色的实例 我做了一个音乐播放器,其中用ListView显示歌曲列表,当我点击某一首歌时,希望这首歌所在的item的背景颜色改变,以突出显示所选择的歌曲. 首先我想到的是在ItemClickListener里面写,如下: private View formerView=null; private class ListViewClickListener implements OnItemClickListener{ @Override public voi

  • Android控件ListView使用方法详解

    Android控件ListView使用方法介绍,具体如下 一.ListView的简单用法 首先新建一个ListViewTest项目,并让Android Studio自动创建好活动.然后修改activity_main.xml中的代码,如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/re

  • Android 中通过ViewDragHelper实现ListView的Item的侧拉划出效果

    先来看看,今天要实现的自定义控件效果图: 关于ViewDragHelper的使用,大家可以先看这篇文章ViewDragHelper的使用介绍 实现该自定义控件的大体步骤如下: 1.ViewDragHelper使用的3部曲,初始化ViewDragHelper,传递触摸事件,实现ViewDragHelper.Callback抽象类. 2.需要创建2个直接的子View,分别是前景View和背景View,代表ListView每一项Item的布局的组成,如下所示: 未划出时显示的FrontView: 划出

  • Android使用ListView实现滚轮的动画效果实例

    之前收到一个需求,需要把一个数据展示列表页面做成像滚轮那样的动画效果:中间最大然后向上下两端逐渐缩小.我想了想iOS那边自带滚轮组件,安卓得自己去实现,目前网上仿ios的滚轮组件的也有一些,但是感觉不适合我,我的要求没那么复杂,于是决定自己动手去实现一下. 动手前先分析一下应该怎么做,归根到底只是要实现缩放效果,由中间向两边变小,当一个item越接近中间就放大,越远离中间就缩小.那么可以通过先获取ListView的中点,然后获取当前可视的所有item跟ListView的中点的垂直距离计算出一个比

  • Android实现仿今日头条点赞动画效果实例

    目录 一.前言 二.需求拆分 三.实现方案 1.点赞控件触摸事件处理 2.点赞动画的实现 2.1.点赞效果图片的获取和存储管理 2.2.点赞表情图标动画实现 2.3.点赞次数和点赞文案的绘制 3.存放点赞动画的容器 4.启动动画 四.遇到的问题 五.实现效果 六.完整代码获取 七.参考和感谢 总结 一.前言 我们在今日头条APP上会看到点赞动画效果,感觉非常不错,正好公司有点赞动画的需求,所以有了接下来的对此功能的实现的探索. 二.需求拆分 仔细观察点赞交互,看出大概以下几个步骤: 1:点赞控件

  • Android直播app送礼物连击动画效果(实例代码)

    最近在做公司的直播项目,需要实现一个观看端连击送礼物的控件: 直接上代码: /** * @author yangyinglong on 2017/7/11 16:52. * @Description: todo(这里用一句话描述这个类的作用) * @Copyright Copyright (c) 2017 Tuandai Inc. All Rights Reserved. */ public class CustomGiftView extends LinearLayout { private

  • android实现直播点赞飘心动画效果

    前段时间在写直播的时候,需要观众在看直播的时候点赞的效果,在此参照了腾讯大神写的点赞(飘心动画效果).下面是效果图: 1.自定义飘心动画的属性 在attrs.xml 中增加自定义的属性 <!-- 飘心动画自定义的属性 --> <declare-styleable name="HeartLayout"> <attr name="initX" format="dimension"/> <attr name=&

  • Android仿支付宝的头部伸缩动画效果

    Android5.0推出的MaterialDesign库包含了处理头部工具栏的多个控件,不但允许自定义顶部导航栏,而且导航栏高度是可以伸缩的.如此一来,一方面导航栏能够放得下更多控件,另一方面在用户想看具体内容时也能腾出更多的屏幕空间. 这么说可能比较抽象,那就先来看看两张导航栏的效果图,第一张是导航栏完全展开时的界面,此时页面头部的导航栏占据了较大部分的高度: 第二张是导航栏完全收缩时的界面,此时头部导航栏只剩矮矮的一个长条. 看起来很眼熟是不是,上面的截图正是仿支付宝首页的头部效果.如果你熟

  • Android实现左右摆动的球体动画效果

    首先,看一下效果 可能各位在别处看到过类似的东西,我在微信的文章末尾看到有个玩意,感觉有意思,就用代码实现一下.这篇文章主要把握写代码的思路展示一下. 看到上图,我想各位能想到最简单的实现方案就是用动画,切很多图出来,然后就可以轻松实现了.为了不让自己再舒适区里呆的太安逸,就弄点麻烦的:通过计算来实现.文章的末尾会将全部代码贴出,复制可以直接运行. 需要回忆的知识 重力势能 E = mgh 动能 E = ½mv² 在理想状态下,动能和重力式能可以相互转换,且能量守恒 如果不想太注意细节,以上的知

  • Android编程实现ImageView图片抛物线动画效果的方法

    本文实例讲述了Android编程实现ImageView图片抛物线动画效果的方法.分享给大家供大家参考,具体如下: 想实现抛物线动画,必须知道抛物线的方程,这时候数学其作用了,假如有如图的抛物线: 按照抛物线的方程特别,知道任何的三点可以确定一条抛物线,由已知抛物线的标注 方程为 y = ax² + bx + c:假设A1坐标为(0,0),A2坐标为(300,0),A3坐标为(150,300):联合解方程得知该抛物线的方程为 y = -1/75 x² + 4x:由此方程,我们可以确定抛物线x和y的

  • Android 自定义view实现水波纹动画效果

    在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了个让人兴奋的效果,兴致高昂的来找你,看了之后目的很明确,当然就是希望你能给她: 在这样的关键时候,身子板就一定得硬了,可千万别说不行,爷们儿怎么能说不行呢: 好了,为了让大家都能给妹纸们想要的,后面会逐渐分享一些比较比较不错的效果,目的只有一个,通过自定义view实现我们所能实现的动效: 今天主要分享水波纹效果: 1.标准正余弦水波纹: 2.非标准圆形液柱水波纹: 虽说都是水波纹,但两者在实现上差异是比较大的,一个

  • Android编程之界面跳动提示动画效果实现方法

    本文实例讲述了Android编程之界面跳动提示动画效果实现方法.分享给大家供大家参考,具体如下: 上一个效果图: 先上布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" a

  • Android开发中MJRefresh自定义刷新动画效果

    [一]常见用法 最原始的用法,耦合度低,但是不能统一管理.我们需要在每一个控制器都写以下代码,很繁琐,以后项目修改起来更繁琐,得一个控制器一个控制器的去定位.修改. 1.1 使用默认刷新(耦合度底,但是想统一修改起来特别麻烦) self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ //在这里执行刷新操作 }]; self.tableView.mj_header = [MJRefreshNorm

随机推荐