2019独角兽企业重金招聘Python工程师标准>>>

注意:本次修改,修补了之前的部分bug

android中展开动画主要有2中,Translate和Scale,但运行效果并不像javascript中jQuery(id).slideDown()那么完美,在这里,我们借助动画机制,实现ListView的展开Expand Open,收缩 Expand Close动画。

这些效果在《去哪儿旅行app》和《酷狗音乐app》被广泛使用,我们这里模仿ListView的展开收缩式动画。

先来看图说话,点击item,被点击的Item以下部分会慢慢下滑。

好了,上代码

dimens.xml,这里是重点,因为下滑的前提是,尺寸必须是已知的,否则无法正常下滑

<dimen name="bottom_item_height">50dip</dimen>
<!--防止布局bug,所以需要设置一个数值区间大于bottom_item_height的复数-->
<dimen name="_bottom_item_height">-50.5dip</dimen>

主布局文件listview_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/main_listview"android:layout_width="match_parent"android:layout_height="match_parent"android:listSelector="@android:color/transparent"android:dividerHeight="0.7dip"android:choiceMode="none"android:divider="#d7d7d7"android:orientation="vertical" ></ListView>

listview_item.xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dip" android:orientation="horizontal"android:paddingLeft="15dip"android:paddingRight="15dip"><TextViewandroid:id="@+id/song_id_title_tv"android:layout_width="0dip"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_weight="1"android:text="一片艳阳天"android:textColor="#333333"android:textSize="18sp" /><ImageViewandroid:id="@+id/song_id_switcher_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:src="@drawable/kg_item_ic_btn_toggle_menu_default" /></LinearLayout><LinearLayoutandroid:id="@+id/song_id_panel_li"android:layout_width="match_parent"android:layout_height="@@dimen/bottom_item_height"android:layout_marginBottom="@dimen/_bottom_item_height"android:background="#333333"android:gravity="center_vertical"android:orientation="horizontal" ><ImageViewandroid:layout_weight="1"android:layout_width="0dip"android:id="@+id/imageView1"android:layout_height="match_parent"android:scaleType="center"android:src="@drawable/kg_ic_player_menu_download" /><ImageViewandroid:id="@+id/imageView2"android:layout_weight="1"android:layout_width="0dip"android:layout_height="match_parent"android:scaleType="center"android:src="@drawable/audio_identify_add_press" /><ImageViewandroid:id="@+id/imageView3"android:layout_weight="1"android:layout_width="0dip"android:layout_height="match_parent"android:scaleType="center"android:src="@drawable/audio_identify_share_press" /><ImageViewandroid:id="@+id/imageView4"android:layout_weight="1"android:layout_width="0dip"android:layout_height="match_parent"android:scaleType="center"android:src="@drawable/fm_distinguish_favorite" /></LinearLayout>
</LinearLayout>

自定义动画

package com.example.explistview;import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.LinearLayout.LayoutParams;import com.example.actiontabbar.R;public class ExpandAnimation extends Animation {private View mTargetView;private boolean isExpandDown;public ExpandAnimation(View mTargetView, boolean isExpandDown,int defaultHeight) {super();this.mTargetView = mTargetView;this.isExpandDown = isExpandDown;setDuration(500L);setInterpolator(new AccelerateDecelerateInterpolator());setFillAfter(true);resetViewHeight(mTargetView, defaultHeight);}/*** 动画开始前,务必保证targetView的高度是存在的* @param v* @param defaultHeight*/private void resetViewHeight(View v,int defaultHeight) {LayoutParams lp = (LayoutParams) v.getLayoutParams();lp.height = v.getContext().getResources().getDimensionPixelSize(R.dimen.bottom_item_height);v.setLayoutParams(lp);}@Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) {super.applyTransformation(interpolatedTime, t);int height = mTargetView.getHeight();/*** 注意 这里的 LayoutParams 类型应该和mTargetView的parentView相关,* 比如LinearLayout,这里的类型应该是android.widget.LinearLayout.LayoutParams* 不推荐使用 ViewGroup.LayoutParams,因为不能改变外边距*/LayoutParams layoutParams = (LayoutParams) mTargetView.getLayoutParams();if(isExpandDown){layoutParams.bottomMargin = -height  + (int) (height*interpolatedTime);}else{layoutParams.bottomMargin = -(int) (height*interpolatedTime);}mTargetView.setLayoutParams(layoutParams);mTargetView.getParent().requestLayout();}
}

Activity文件

package com.example.explistview;import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;import com.example.actiontabbar.R;
import com.nineoldandroids.view.ViewHelper;
import com.nineoldandroids.view.ViewPropertyAnimator;public class AnimExpandActivity extends ActionBarActivity {private ListView mListView;private final List<Song> songList = new ArrayList<AnimExpandActivity.Song>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.listview_layout);mListView = (ListView) findViewById(R.id.main_listview);loadTestData();mListView.setAdapter(new ListSongItemAdapter(this, songList));}private void loadTestData() {songList.add(new Song("苏有朋-珍惜", false));songList.add(new Song("崔子格-卜卦", false));songList.add(new Song("吴奇隆-祝你一路顺风", false));songList.add(new Song("马天宇-该死的温柔", false));songList.add(new Song("陈奕迅-梦想天空分外蓝", false));songList.add(new Song("陈奕迅-爱情转移", false));songList.add(new Song("陈奕迅-十年", false));songList.add(new Song("张宇-雨一直下", false));songList.add(new Song("王筝-我们都是好孩子", false));songList.add(new Song("筷子兄弟-小苹果", false));songList.add(new Song("筷子兄弟-老男孩", false));songList.add(new Song("成龙-神话", false));songList.add(new Song("金莎-星月神话", false));songList.add(new Song("金莎-相思垢", false));songList.add(new Song("许嵩-断桥残雪", false));songList.add(new Song("许嵩-半城烟沙", false));songList.add(new Song("许嵩-灰色头像", false));songList.add(new Song("许嵩-庐州月", false));songList.add(new Song("陈坤-好久没回家", false));}private class ListSongItemAdapter extends BaseAdapter {private final List<Song> dataSource = new ArrayList<AnimExpandActivity.Song>();private LayoutInflater mLayoutInflater = null;private int dimensionPixelSize = 0;public ListSongItemAdapter(Context cxt, List<Song> dataSource) {this.dataSource.addAll(dataSource);mLayoutInflater = LayoutInflater.from(cxt);dimensionPixelSize  = cxt.getResources().getDimensionPixelSize(R.dimen.bottom_item_height);}@Overridepublic int getCount() {return dataSource.size();}@Overridepublic Object getItem(int position) {return dataSource.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {SongViewHolder songViewHolder = null;if (convertView == null|| !SongViewHolder.class.isInstance(convertView.getTag())) {convertView = mLayoutInflater.inflate(R.layout.listview_item,null);songViewHolder = new SongViewHolder(convertView);convertView.setTag(songViewHolder);} else {songViewHolder = (SongViewHolder) convertView.getTag();}Song song = dataSource.get(position);LayoutParams lp = (LayoutParams) songViewHolder.targetPanel.getLayoutParams();if(song.isOpen){ViewHelper.setRotation(songViewHolder.switcherIv, 180f);lp.bottomMargin = 0;lp.height =  dimensionPixelSize;}else{ViewHelper.setRotation(songViewHolder.switcherIv, 0f);lp.bottomMargin = - dimensionPixelSize;//高度是0,lp.bottomMargin值无效,这里之所以设置高度为0,因为为了防止布局耗时导致绘制不及时,从而出现错误显示lp.height = 0;}songViewHolder.targetPanel.setLayoutParams(lp);songViewHolder.switcherIv.setOnClickListener(switcherClickListener);songViewHolder.switcherIv.setTag(position);songViewHolder.titleTv.setText(position + " " + song.name);return convertView;}}private class Song implements Serializable {private String name;private boolean isOpen;public Song(String name, boolean isOpen) {super();this.name = name;this.isOpen = isOpen;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void setOpen(boolean isOpen) {this.isOpen = isOpen;}public boolean isOpen() {return isOpen;}@Overridepublic String toString() {return "Song [name=" + name + ", isOpen=" + isOpen + "]";}}private class SongViewHolder implements Serializable {private View contentView;private TextView titleTv;private ImageView switcherIv;private View targetPanel;public SongViewHolder(View contentView) {this.contentView = contentView;titleTv = (TextView) contentView.findViewById(R.id.song_id_title_tv);switcherIv = (ImageView) contentView.findViewById(R.id.song_id_switcher_btn);targetPanel = contentView.findViewById(R.id.song_id_panel_li);}}private View.OnClickListener switcherClickListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {int position = (Integer) v.getTag();final BaseAdapter adapter = (BaseAdapter) mListView.getAdapter();Song item = (Song) adapter.getItem(position);item.setOpen(!item.isOpen());ViewGroup itemView = (ViewGroup) v.getParent().getParent();SongViewHolder songViewHolder = (SongViewHolder) itemView.getTag();Toast.makeText(AnimExpandActivity.this,"position=" + position + ",title=" + item.getName(),Toast.LENGTH_SHORT).show();int defaultHeight = getResources().getDimensionPixelSize(R.dimen.bottom_item_height);itemView.startAnimation(new ExpandAnimation(songViewHolder.targetPanel, item.isOpen(),defaultHeight));rotateSwitcherIcon(v, item);}};/*** 旋转切换图标* @param v* @param item*/private void rotateSwitcherIcon(View v, Song item){float degree = item.isOpen() ? 180 : 0;ViewPropertyAnimator.animate(v).setDuration(500).setInterpolator(new AccelerateDecelerateInterpolator()).rotation(degree).start();}}

----------------------------------------------------------

这里使用了较为原始的自定义动画的方式,推荐读者能够使用 属性动画自定义这种实现

可参考链接 http://blog.csdn.net/lingling1420q/article/details/38678493

目前为止,这个例子还需要进行优化,等时间再说吧。

try doing it!

转载于:https://my.oschina.net/ososchina/blog/405544

Android 实现ListView的展开式动画ExpandAnimation相关推荐

  1. Android—ListView Item 展开动画效果

    Android-ListView Item 展开动画效果 最近在做一个关于ListView item的展开效果,类似于 "粮仓" App 的商店页面,点击Item,展开显示子Vie ...

  2. android listview下拉刷新动画,android 安卓 listview 支持下拉刷新 上拉加载更多

    [1]重写listViewimport java.text.SimpleDateFormat; import java.util.Date; import com.example.testdddlea ...

  3. android笔记listview item加载动画

    效果图: 1.继承listviewactivity ListviewitemActivity extends ListActivity 2.通过下面方式获取listview listview001 = ...

  4. android listview item 展开动画,android的ListView点击item使item展开的做法的实现代码

    本文介绍了android的ListView点击item使item展开的做法的实现代码,分享给大家,具体如下: 效果图: 原理是点击item的时候,重新measure list的各个item的高度 li ...

  5. android listview左右滑动动画效果,Android基于ListView实现类似QQ空间的滚动翻页与滚动加载效果...

    本文实例讲述了Android基于ListView实现类似QQ空间的滚动翻页与滚动加载效果.分享给大家供大家参考,具体如下: 1. 滚动加载 listView.setOnScrollListener(n ...

  6. Xamarin Android组件篇教程RecylerView动画组件RecylerViewAnimators(1)

    Xamarin Android组件篇教程RecylerView动画组件RecylerViewAnimators(1) RecyclerView是比ListView和GridView更为强大的布局视图, ...

  7. Android之ListView异步加载图片且仅显示可见子项中的图片

    折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整 ...

  8. Android 自定义ListView控件,滑动删除

    1.触摸事件 dispatchTouchEvent 判断是否处理触摸动作 onTouchEvent 处理触摸动作 2.Android对于控制和获取View在屏幕很强大 ListView: pointT ...

  9. Android自定义ListView实现仿微信侧滑删除

    经常在遇到问题第一时间都会在网上搜索解决的方法,因此看到很多前辈们的比较精辟的技术文章,学习了很多东西,现在将自己平时工作中开发的一些小功能坐下总结,也写出来,既方便自己理清思路记忆功能块实现思路,又 ...

最新文章

  1. Guava 中的 Stopwatch 是个什么鬼?
  2. 源码编译安装percona-xtrabackup-2.3.2
  3. 摩托罗拉ex232java_摩托罗拉ex232r如何刷机?摩托罗拉ex232r评测
  4. 如何腾出计算机内存,win7系统(取消)删除虚拟内存让硬盘空间轻松腾出来
  5. Run-time error “70“:Permission denied
  6. cygwin清屏技巧
  7. 管理感情:工作犯错了,不要狡辩,不要把错误推到别人身上
  8. 购物商城Web开发第二十二天
  9. matlab数值分析作业答案,Matlab作业3(数值分析)答案
  10. msvcr100.dll解决方法
  11. word表格分开快捷键_Word快捷键一览表
  12. 搞死SAP系统系列 让PO系统宕机
  13. 12:计算2的N次方
  14. JavaScript 数据类型和类型转换
  15. 数据分析项目实战项目二:入驻商用户画像体系
  16. UVM基础-TLM通信机制(二)
  17. mt2523 LinkIt_SDK_v4_GCC_Build_Environment_Guide
  18. 为知所见即所得MarkDown插件
  19. 【JavaSE 第八天】
  20. PHP连接MySQL数据库【展示员工信息】

热门文章

  1. java 国家法定节假日和双休日判断工具类
  2. 中标麒麟 NeoKylin 5.1 安装C++环境
  3. c语言大数运算知乎,为什么知乎上大多数人不推荐C语言入门?
  4. 岛屿周长c语言,岛屿的周长 --leetcode刷题,golang实现
  5. Mysql ERROR 1242 (21000): Subquery returns more than 1 row
  6. python随机生成小写字母表_用小写字母生成大随机字符串的最快方法
  7. 二进制安装k8s v1.22.8集群
  8. 树莓派+motion实现局域网简单监控
  9. GPU与CPU性能比较
  10. Vue+SpringBoot+ElementUI实战学生管理系统-9.教师管理模块