Android实战(橘子娱乐)-首页(第三篇 IRecyclerView自定义刷新头ClassicRefreshHeaderView和SharedPreferencesUtils)

来源:互联网 发布:微信怎么宣传淘宝店铺 编辑:程序博客网 时间:2024/04/30 15:39
前言:
  在  Android实战(橘子娱乐)-首页(第二篇  首页布局与Activity代码)中我们讲解了首页布局xml文件和,MainActivity的核心逻辑代码。然后呢说这篇会讲解一下,IRecyclerView自定义刷新头ClassicRefreshHeaderView的实现,这一个系列的文章都有关联性,如果只是看其中一篇或者跳篇看的话可能思路不是很清晰,所以建议重头看起。接下来依然是一张图,可以看看刷新的效果:

    其实自定义刷新头都是一些常规的逻辑,只要思路清晰,写代码应该不难,接下来我们看看代码:

    ClassicRefreshHeaderView.java
  1. package com.andy.orange.widget;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.view.animation.Animation;
  5. import android.view.animation.AnimationUtils;
  6. import android.widget.ImageView;
  7. import android.widget.ProgressBar;
  8. import android.widget.RelativeLayout;
  9. import android.widget.TextView;
  10. import com.andy.orange.R;
  11. import com.aspsine.irecyclerview.RefreshTrigger;
  12. public class ClassicRefreshHeaderView extends RelativeLayout implements RefreshTrigger {
  13. private ImageView ivArrow;
  14. private ImageView ivSuccess;
  15. private TextView tvRefresh;
  16. private ProgressBar progressBar;
  17. private Animation rotateUp;
  18. private Animation rotateDown;
  19. private boolean rotated = false;
  20. private int mHeight;
  21. public ClassicRefreshHeaderView(Context context) {
  22. this(context, null);
  23. }
  24. public ClassicRefreshHeaderView(Context context, AttributeSet attrs) {
  25. this(context, attrs, 0);
  26. }
  27. public ClassicRefreshHeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
  28. super(context, attrs, defStyleAttr);
  29. //加载布局
  30. inflate(context, R.layout.irecyclerview_refresh_header_view, this);
  31. //初始化view
  32. tvRefresh = (TextView) findViewById(R.id.tvRefresh);
  33. ivArrow = (ImageView) findViewById(R.id.ivArrow);
  34. ivSuccess = (ImageView) findViewById(R.id.ivSuccess);
  35. progressBar = (ProgressBar) findViewById(R.id.progressbar);
  36. //向上旋转动画
  37. rotateUp = AnimationUtils.loadAnimation(context, R.anim.rotate_up);
  38. //向下旋转
  39. rotateDown = AnimationUtils.loadAnimation(context, R.anim.rotate_down);
  40. }
  41. @Override
  42. public void onStart(boolean automatic, int headerHeight, int finalHeight) {
  43. this.mHeight = headerHeight;
  44. progressBar.setIndeterminate(true);
  45. }
  46. @Override
  47. public void onMove(boolean isComplete, boolean automatic, int moved) {
  48. if (!isComplete) {
  49. //设置显示向下的箭头、隐藏进度条和成功图标
  50. ivArrow.setVisibility(VISIBLE);
  51. progressBar.setVisibility(GONE);
  52. ivSuccess.setVisibility(GONE);
  53. //根据临界高度,判断是否刷新
  54. if (moved <= mHeight) {
  55. if (rotated) {
  56. ivArrow.clearAnimation();
  57. ivArrow.startAnimation(rotateDown);
  58. rotated = false;
  59. }
  60. tvRefresh.setText("下拉刷新");
  61. } else {
  62. tvRefresh.setText("释放刷新");
  63. if (!rotated) {
  64. ivArrow.clearAnimation();
  65. ivArrow.startAnimation(rotateUp);
  66. rotated = true;
  67. }
  68. }
  69. }
  70. }
  71. @Override
  72. public void onRefresh() {
  73. //刷新时设置显示进度条和“正在刷新”提示
  74. ivSuccess.setVisibility(GONE);
  75. ivArrow.clearAnimation();
  76. ivArrow.setVisibility(GONE);
  77. progressBar.setVisibility(VISIBLE);
  78. tvRefresh.setText("正在刷新");
  79. }
  80. @Override
  81. public void onRelease() {
  82. }
  83. @Override
  84. public void onComplete() {
  85. //刷新完成以后,显示刷新完成
  86. rotated = false;
  87. ivSuccess.setVisibility(VISIBLE);
  88. ivArrow.clearAnimation();
  89. ivArrow.setVisibility(GONE);
  90. progressBar.setVisibility(GONE);
  91. tvRefresh.setText("刷新完成");
  92. }
  93. @Override
  94. public void onReset() {
  95. rotated = false;
  96. ivSuccess.setVisibility(GONE);
  97. ivArrow.clearAnimation();
  98. ivArrow.setVisibility(GONE);
  99. progressBar.setVisibility(GONE);
  100. }
  101. }
    分析:其实思路就是在类的构造函数中去加载布局,然后让类去继承IRecyclerView关联的RefreashTrigger接口实现在不同状态中做不同的操作,比如刷新前显示刷新前的图片、刷新时候显示刷新的图片,刷新结束后显示刷新结束的图片。
接下来是inflate的布局文件:
irecyclerview_refresh_header_view.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <merge xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="60dp">
  5. <ImageView
  6. android:id="@+id/ivArrow"
  7. android:layout_width="wrap_content"
  8. android:layout_height="wrap_content"
  9. android:layout_centerVertical="true"
  10. android:layout_marginRight="48dp"
  11. android:layout_toLeftOf="@+id/tvRefresh"
  12. android:background="@drawable/expend_bottom" />
  13. <ImageView
  14. android:id="@+id/ivSuccess"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:layout_centerVertical="true"
  18. android:layout_marginRight="48dp"
  19. android:layout_toLeftOf="@+id/tvRefresh"
  20. android:background="@drawable/refresh_end" />
  21. <ProgressBar
  22. android:id="@+id/progressbar"
  23. style="?android:attr/progressBarStyleSmallInverse"
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:layout_centerVertical="true"
  27. android:layout_marginRight="48dp"
  28. android:layout_toLeftOf="@+id/tvRefresh" />
  29. <TextView
  30. android:id="@+id/tvRefresh"
  31. android:layout_width="150dp"
  32. android:layout_height="wrap_content"
  33. android:layout_centerInParent="true"
  34. android:gravity="center" />
  35. </merge>
    比较简单,这里就不讲了,主要讲讲其中的rotateUp和rotateDown两个动画,其实就是实现下拉高度大于刷新头高度时,实现ImageView也就是向下的箭头向上旋转180度,在下拉高度低于刷新头高度时向下旋转180度。我们来看看其中一个文件:
rotate_down.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <rotate xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:duration="150"
  4. android:fillAfter="true"
  5. android:fromDegrees="-180"
  6. android:pivotX="50%"
  7. android:pivotY="50%"
  8. android:repeatCount="0"
  9. android:toDegrees="0"
  10. android:interpolator="@android:anim/linear_interpolator"
  11. />
  12. <!--
  13. android:fillAfter="true"//设置保存结束时的状态
  14. android:fromDegrees="-180" android:toDegrees="0"//表示旋转的开始和结束角度
  15. android:pivotX="50%" android:pivotY="50%"//设置旋转的中心点
  16. android:repeatCount="0"//设置重复次数
  17. android:interpolator="@android:anim/linear_interpolator"//设置在旋转过程中的速度变化
  18. android:duration="150"//不用讲是动画时长
  19. -->
    注释都很清楚,rotate_up.xml就不贴出来了,伙伴儿可以试着自己写,我相信你可以的。其实第二篇中我们有用到SharedPreferencesUtils这个工具类,但是没有实际讲他里面我都封装了些什么,接下来我们来看看这个工具类的代码:
  1. package com.andy.orange.utils;
  2. import android.content.Context;
  3. import android.content.SharedPreferences;
  4. import android.util.Log;
  5. /**
  6. * Created by Andy Lau on 2017/8/10.
  7. */
  8. public class SharedPreferencesUtils {
  9. private static final String TAG ="Andy";
  10. private static SharedPreferences sp;
  11. private static void init(Context context) {
  12. if (sp == null) {
  13. Log.d(TAG,context.toString());
  14. sp=context.getSharedPreferences("login_preferences",Context.MODE_PRIVATE);
  15. }
  16. }
  17. public static void setSharedData(Context context, String key, Object value, String type){
  18. if (type.isEmpty()) {
  19. return;
  20. }
  21. if (sp == null) {
  22. init(context);
  23. }
  24. if (type.equals("int")){
  25. sp.edit().putInt(key,(int)value).commit();
  26. }else if (type.equals("string")){
  27. sp.edit().putString(key,(String)value).commit();
  28. }else if (type.equals("boolean")){
  29. sp.edit().putBoolean(key,(boolean)value).commit();
  30. }else if (type.equals("float")){
  31. sp.edit().putFloat(key,(float)value).commit();
  32. }else {
  33. sp.edit().putLong(key,(long)value).commit();
  34. }
  35. }
  36. public static Object readSharedData(Context context, String key, String type){
  37. Object result = null;
  38. if (type.isEmpty()) {
  39. return null;
  40. }
  41. if (sp == null) {
  42. init(context);
  43. }
  44. if (type.equals("int")){
  45. result=sp.getInt(key,0);
  46. }else if (type.equals("string")){
  47. result=sp.getString(key,"");
  48. }else if (type.equals("boolean")){
  49. result=sp.getBoolean(key,false);
  50. }else if (type.equals("float")){
  51. result=sp.getFloat(key,0f);
  52. }else {
  53. result=sp.getLong(key,0L);
  54. }
  55. return result;
  56. }
  57. }
    比较简单就是建一个叫 login_preferences 的SharedPreferences保存登录状态信息,另外封装两个读和写的方法,提供使用。ok,这篇的任务完成,接下来我们会学习一下,首页IRecyclerView的适配器 MainRecyclerViewAdapter 部分的实现逻辑,看他是如何将数据和布局绑定在一起的。
 
阅读全文
0 0
原创粉丝点击