12.值动画、测量规则

应用详情安全界面
DetailSafeHolder  
  1. public class DetailSafeHolder extends BaseHolder<AppInfo> implements
  2. OnClickListener {
  3. @ViewInject(R.id.safe_layout)
  4. private RelativeLayout safe_layout;
  5. @ViewInject(R.id.safe_content)
  6. private LinearLayout safe_content;
  7. @ViewInject(R.id.safe_arrow)
  8. private ImageView safe_arrow;
  9. ImageView[] ivs;
  10. ImageView[] iv_des;
  11. TextView[] tv_des;
  12. LinearLayout[] des_layout;
  13. @Override
  14. public View initView() {
  15. View view = UiUtils.inflate(R.layout.detail_safe);
  16. ViewUtils.inject(this, view);
  17. ivs = new ImageView[4]; // 初始化标题栏的图片
  18. ivs[0] = (ImageView) view.findViewById(R.id.iv_1);
  19. ivs[1] = (ImageView) view.findViewById(R.id.iv_2);
  20. ivs[2] = (ImageView) view.findViewById(R.id.iv_3);
  21. ivs[3] = (ImageView) view.findViewById(R.id.iv_4);
  22. iv_des = new ImageView[4]; // 初始化每个条目描述的图片
  23. iv_des[0] = (ImageView) view.findViewById(R.id.des_iv_1);
  24. iv_des[1] = (ImageView) view.findViewById(R.id.des_iv_2);
  25. iv_des[2] = (ImageView) view.findViewById(R.id.des_iv_3);
  26. iv_des[3] = (ImageView) view.findViewById(R.id.des_iv_4);
  27. tv_des = new TextView[4]; // 初始化每个条目描述的文本
  28. tv_des[0] = (TextView) view.findViewById(R.id.des_tv_1);
  29. tv_des[1] = (TextView) view.findViewById(R.id.des_tv_2);
  30. tv_des[2] = (TextView) view.findViewById(R.id.des_tv_3);
  31. tv_des[3] = (TextView) view.findViewById(R.id.des_tv_4);
  32. des_layout = new LinearLayout[4]; // 初始化条目线性布局
  33. des_layout[0] = (LinearLayout) view.findViewById(R.id.des_layout_1);
  34. des_layout[1] = (LinearLayout) view.findViewById(R.id.des_layout_2);
  35. des_layout[2] = (LinearLayout) view.findViewById(R.id.des_layout_3);
  36. des_layout[3] = (LinearLayout) view.findViewById(R.id.des_layout_4);
  37. LayoutParams layoutParams = safe_content.getLayoutParams();
  38. layoutParams.height=0;//默认为0
  39. safe_content.setLayoutParams(layoutParams);
  40. //必须经过上面这三步才能设置大小
  41. safe_arrow.setImageResource(R.drawable.arrow_down);
  42. return view;
  43. }
  44. @Override
  45. public void refreshView(AppInfo data) {
  46. safe_layout.setOnClickListener(this);
  47. List<String> safeUrl = data.getSafeUrl();
  48. List<String> safeDesUrl = data.getSafeDesUrl();
  49. List<String> safeDes = data.getSafeDes();
  50. List<Integer> safeDesColor = data.getSafeDesColor(); // 0 1 2 3
  51. for (int i = 0; i < 4; i++) {
  52. if (i < safeUrl.size() && i < safeDesUrl.size()
  53. && i < safeDes.size() && i < safeDesColor.size()) {
  54. ivs[i].setVisibility(View.VISIBLE);
  55. des_layout[i].setVisibility(View.VISIBLE);
  56. bitmapUtils.display(ivs[i], HttpHelper.URL + "image?name="
  57. + safeUrl.get(i));
  58. bitmapUtils.display(iv_des[i], HttpHelper.URL + "image?name="
  59. + safeDesUrl.get(i));
  60. tv_des[i].setText(safeDes.get(i));
  61. // 根据服务器数据显示不同的颜色,有可能文字颜色不一样
  62. int color;
  63. int colorType = safeDesColor.get(i);
  64. if (colorType >= 1 && colorType <= 3) {
  65. color = Color.rgb(255, 153, 0); // 00 00 00
  66. } else if (colorType == 4) {
  67. color = Color.rgb(0, 177, 62);
  68. } else {
  69. color = Color.rgb(122, 122, 122);
  70. }
  71. tv_des[i].setTextColor(color);
  72. } else {
  73. ivs[i].setVisibility(View.GONE);
  74. des_layout[i].setVisibility(View.GONE);
  75. }
  76. }
  77. }
  78. boolean flag=false;//默认不展开
  79. @Override
  80. public void onClick(View v) {
  81. if (v.getId() == R.id.safe_layout) {
  82. int startHeight;
  83. int targetHeight;
  84. if (!flag) { // 展开的动画
  85. startHeight=0;
  86. targetHeight=getMeasureHeight();
  87. flag = true;
  88. //safe_content.setVisibility(View.VISIBLE);这样写也可以,不过显的特别突兀
  89. safe_content.getMeasuredHeight(); // 0
  90. } else {
  91. flag=false;
  92. //safe_content.setVisibility(View.GONE);
  93. startHeight=getMeasureHeight();
  94. targetHeight=0;
  95. }
  96. // 值动画
  97. ValueAnimator animator=ValueAnimator.ofInt(startHeight,targetHeight);
  98. final RelativeLayout.LayoutParams layoutParams = (android.widget.RelativeLayout.LayoutParams) safe_content.getLayoutParams();
  99. animator.addUpdateListener(new AnimatorUpdateListener() { // 监听值的变化
  100. @Override
  101. public void onAnimationUpdate(ValueAnimator animator) {
  102. int value=(Integer) animator.getAnimatedValue();// 运行当前时间点的一个值
  103. layoutParams.height=value;
  104. safe_content.setLayoutParams(layoutParams);// 刷新界面
  105. System.out.println(value);
  106. }
  107. });
  108. animator.addListener(new AnimatorListener() { // 监听动画执行
  109. //当动画开始执行的时候调用
  110. @Override
  111. public void onAnimationStart(Animator arg0) {
  112. // TODO Auto-generated method stub
  113. }
  114. @Override
  115. public void onAnimationRepeat(Animator arg0) {
  116. }
  117. @Override
  118. public void onAnimationEnd(Animator arg0) {
  119. if(flag){
  120. safe_arrow.setImageResource(R.drawable.arrow_up);
  121. }else{
  122. safe_arrow.setImageResource(R.drawable.arrow_down);
  123. }
  124. }
  125. @Override
  126. public void onAnimationCancel(Animator arg0) {
  127. }
  128. });
  129. animator.setDuration(500);
  130. animator.start();
  131. }
  132. }
  133. //onMeasure() 制定测量的规则
  134. // measure() 实际测量
  135. /**
  136. * 获取控件实际的高度
  137. */
  138. public int getMeasureHeight(){
  139. int width = safe_content.getMeasuredWidth(); // 由于宽度不会发生变化 宽度的值取出来
  140. safe_content.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;// 让高度包裹内容,可以不写
  141. //得先重新设置完规则再测量
  142. // 参数1 测量控件mode 参数2 大小
  143. int widthMeasureSpec=MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, width); // mode+size
  144. int heightMeasureSpec=MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, 1000);// 我的高度 最大是1000
  145. // 测量规则 宽度是一个精确的值width, 高度最大是1000,以实际为准
  146. safe_content.measure(widthMeasureSpec, heightMeasureSpec); // 通过该方法重新测量控件
  147. return safe_content.getMeasuredHeight();
  148. }
  149. }

应用详情描述界面
DetailDesHolder :这个麻烦点,因为它默认是从7行的高度到包裹内容,所以得先计算出7行的高度
  1. public class DetailDesHolder extends BaseHolder<AppInfo> implements OnClickListener {
  2. @ViewInject(R.id.des_content)
  3. private TextView des_content;
  4. @ViewInject(R.id.des_author)
  5. private TextView des_author;
  6. @ViewInject(R.id.des_arrow)
  7. private ImageView des_arrow;
  8. @ViewInject(R.id.des_layout)
  9. private RelativeLayout des_layout;
  10. @Override
  11. public View initView() {
  12. View view=UiUtils.inflate(R.layout.detail_des);
  13. ViewUtils.inject(this, view);
  14. return view;
  15. }
  16. @Override
  17. public void refreshView(AppInfo data) {
  18. des_content.setText(data.getDes());
  19. des_author.setText("作者:"+data.getAuthor());
  20. des_layout.setOnClickListener(this);
  21. //des_content 起始高度7行的高度
  22. LayoutParams layoutParams = des_content.getLayoutParams();
  23. layoutParams.height=getShortMeasureHeight();
  24. des_content.setLayoutParams(layoutParams);
  25. des_arrow.setImageResource(R.drawable.arrow_down);
  26. }
  27. /**
  28. * 获取7行的高度
  29. * @return
  30. */
  31. public int getShortMeasureHeight(){
  32. // 复制一个新的TextView 用来测量,最好不要在之前的TextView测量 有可能影响其它代码执行
  33. TextView textView=new TextView(UiUtils.getContext());
  34. textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);//设置字体大小14dp
  35. textView.setMaxLines(7);
  36. textView.setLines(7);// 强制有7行
  37. int width=des_content.getMeasuredWidth(); // 开始宽度
  38. //得先重新设置完规则再测量
  39. int widthMeasureSpec=MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, width);
  40. int heightMeasureSpec=MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, 1000);
  41. textView.measure(widthMeasureSpec, heightMeasureSpec);
  42. return textView.getMeasuredHeight();
  43. }
  44. /**
  45. * 获取TextView 自己本身的高度
  46. * @return
  47. */
  48. public int getLongMeasureHeight(){
  49. int width=des_content.getMeasuredWidth(); // 开始宽度
  50. des_content.getLayoutParams().height= ViewGroup.LayoutParams.WRAP_CONTENT;// 高度包裹内容
  51. int widthMeasureSpec=MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, width);
  52. int heightMeasureSpec=MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, 1000);
  53. des_content.measure(widthMeasureSpec,heightMeasureSpec);//
  54. return des_content.getMeasuredHeight();
  55. }
  56. boolean flag;// true展开了 false 没有展开,不写的话默认是false
  57. @Override
  58. public void onClick(View v) {
  59. expand();
  60. }
  61. ScrollView scrollView;
  62. // scrollView.scrollTo(0, scrollView.getMeasuredHeight())
  63. /**
  64. * 获取到界面的ScollView,这样可以点箭头时就到了最后
  65. */
  66. public ScrollView getScrollView(View view){
  67. ViewParent parent = view.getParent();
  68. if(parent instanceof ViewGroup){
  69. ViewGroup group=(ViewGroup) parent;
  70. if(group instanceof ScrollView){
  71. return (ScrollView)group;
  72. }else{
  73. return getScrollView(group);//用递归,知道获取到ScrollView
  74. }
  75. }else{
  76. return null;
  77. }
  78. }
  79. private void expand() {
  80. scrollView=getScrollView(des_layout);
  81. int startHeight;
  82. int targetHeight;
  83. if(!flag){
  84. flag=true;
  85. startHeight=getShortMeasureHeight();
  86. targetHeight=getLongMeasureHeight();
  87. }else{
  88. flag=false;
  89. startHeight=getLongMeasureHeight();
  90. targetHeight=getShortMeasureHeight();
  91. }
  92. final LayoutParams layoutParams = des_content.getLayoutParams();
  93. ValueAnimator animator=ValueAnimator.ofInt(startHeight,targetHeight);
  94. animator.addUpdateListener(new AnimatorUpdateListener() {
  95. @Override
  96. public void onAnimationUpdate(ValueAnimator animation) {
  97. int value=(Integer) animation.getAnimatedValue();
  98. layoutParams.height=value;
  99. des_content.setLayoutParams(layoutParams);
  100. scrollView.scrollTo(0, scrollView.getMeasuredHeight());// 让scrollView 移动到最下面
  101. }
  102. });
  103. animator.addListener(new AnimatorListener() { // 监听动画执行
  104. //当动画开始执行的时候调用
  105. @Override
  106. public void onAnimationStart(Animator arg0) {
  107. // TODO Auto-generated method stub
  108. }
  109. @Override
  110. public void onAnimationRepeat(Animator arg0) {
  111. }
  112. @Override
  113. public void onAnimationEnd(Animator arg0) {
  114. if(flag){
  115. des_arrow.setImageResource(R.drawable.arrow_up);
  116. }else{
  117. des_arrow.setImageResource(R.drawable.arrow_down);
  118. }
  119. }
  120. @Override
  121. public void onAnimationCancel(Animator arg0) {
  122. }
  123. });
  124. animator.setDuration(500);//设置动画持续时间
  125. animator.start();
  126. }
  127. }
附件里是一个兼容版本的值动画第三方架包,导包的时候导这个

修改ListBaseAdapter,添加这个方法,每个应用界面、游戏界面就都能点listview了
  1. @Override
  2. public void onInnerItemClick(int position) {
  3. super.onInnerItemClick(position);
  4. Toast.makeText(UiUtils.getContext(), "position:"+position, 0).show();
  5. AppInfo appInfo = datas.get(position);
  6. Intent intent=new Intent(UiUtils.getContext(), DetailActivity.class);
  7. intent.putExtra("packageName", appInfo.getPackageName());
  8. UiUtils.startActivity(intent);
  9. }
UiUtils 
  1. /**
  2. * 可以打开activity
  3. * @param intent
  4. */
  5. public static void startActivity(Intent intent) {
  6. // 如果不在activity里去打开activity 需要指定任务栈 需要设置标签
  7. if(BaseActivity.activity==null){
  8. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  9. getContext().startActivity(intent);
  10. }else{
  11. BaseActivity.activity.startActivity(intent);
  12. }
  13. }
BaseActivity 
 
  1. public static BaseActivity activity;
  2. @Override
  3. protected void onResume() {
  4. super.onResume();
  5. activity=this;
  6. }
  7. @Override
  8. protected void onPause() {
  9. super.onPause();
  10. activity=null;
  11. }

 












附件列表

    原文地址:https://www.cnblogs.com/sixrain/p/4979261.html