編輯:關於Android編程
好久沒有寫博客了,今天我就寫一個listview的下拉刷新分享給大家,希望對大家學習或者工作上有所幫助,其實呢,大家都知道,在現在的app當中,下拉刷新是比較常用的功能,用到的地方太多了,所以,今天我也就結合自己的思想給家真理一下,那麼好,接下來,讓我們一起學習,讓你分分鐘寫出自己想要的自定義listview下拉刷新
一:實現思路
1.實現將listview添加頭部view,也就是下拉要出現是頭部布局
2.將頭部的view給隱藏(這點需要特別注意)
3.給listview設置滑動監聽(用於判斷是否到頭部)
4.設置手勢事件,手指移動的時候的所做的操作
二:源碼實例
1.自定義控件
package com.zengtao.refreshview; import java.text.SimpleDateFormat; import java.util.Date; import android.annotation.SuppressLint; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.RotateAnimation; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ImageView; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import com.zengtao.pulltorefreshtest.R; /** * 下拉刷新listview * * @author zengtao 2015年3月17日 下午7:13:55 */ public class RefreshableView extends ListView implements OnScrollListener { /** 下拉刷新的頭部 */ private View headerView; /** 頭部的箭頭 */ private ImageView arrawImage; /** 更新刷新之後的時間 */ private TextView lastUpdatTime; /** 刷新的一個狀態 */ private TextView stateMessage; /** 加載進度 */ private ProgressBar progressBar; /** 獲取頭部文件的高度 */ private int headerHeight; /** 當前第一個可見的位置 */ private int firstVisibleItem; /** 標記當前是否能刷新 */ private boolean isReflash; /** 按下的y值 */ private int startY; /** 下拉的狀態 */ private int state; /** 正常狀態 */ private final int NONE = 0; /** 提示下拉刷新狀態 */ private final int PULL = 1; /** 提示釋放刷新狀態 */ private final int REFPULL = 2; /** 提示正在刷新 */ private final int LOADING = 3; /** ListView 當前滾動位置 */ private int scorellStatep; /** 數據回調接口 */ private IReflashLinster iReflashLinster; public RefreshableView(Context context) { super(context); initView(context); } public RefreshableView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context); } public RefreshableView(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } /** * 作用:初始化下拉刷新的頭部 * * @param context * :上下文 */ @SuppressLint("InflateParams") private void initView(Context context) { headerView = LayoutInflater.from(context).inflate( R.layout.pull_to_refresh, null); // 初始化試圖 arrawImage = (ImageView) headerView.findViewById(R.id.iv_arrow); stateMessage = (TextView) headerView.findViewById(R.id.pull_state); lastUpdatTime = (TextView) headerView.findViewById(R.id.lastupdatetime); progressBar = (ProgressBar) headerView.findViewById(R.id.progress_bar); // 通知父布局,才能取到多高,否則為0 measureView(headerView); headerHeight = headerView.getMeasuredHeight(); topPadding(-headerHeight); this.addHeaderView(headerView); this.setOnScrollListener(this); } /** * 通知父布局我該占取多少的height 和 width * * @param view * :試圖布局 */ private void measureView(View view) { ViewGroup.LayoutParams p = view.getLayoutParams(); if (p == null) { p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); int tempHeight = p.height; int height; if (tempHeight > 0) { height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY); } else { height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } view.measure(width, height); } /** * 設置header布局的上邊距 * * @param topHeight * : 上邊距高度 */ private void topPadding(int topPadding) { headerView.setPadding(headerView.getPaddingLeft(), topPadding, headerView.getPaddingRight(), headerView.getPaddingBottom()); headerView.invalidate(); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { this.scorellStatep = scrollState; } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { this.firstVisibleItem = firstVisibleItem; } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: // listview 已經滑到頭部 if (firstVisibleItem == 0) { isReflash = true; startY = (int) ev.getY(); } break; case MotionEvent.ACTION_MOVE: // 移動的時候所做的操作 onMove(ev); break; case MotionEvent.ACTION_UP: // 松開的時候看是處於什麼狀態 if (state == REFPULL) { state = LOADING; // 可以加載數據了 reflashViewBySate(); reflashComplete(); iReflashLinster.reflash(); } else if (state == PULL) { state = NONE; isReflash = false; reflashViewBySate(); } break; } return super.onTouchEvent(ev); } /** * 手指移動的時候的所做的操作 * * @param ev */ private void onMove(MotionEvent ev) { // 是不是能刷新 if (!isReflash) { return; } // 當前移動的位置 int tempY = (int) ev.getY(); int spance = tempY - startY; // 頂部布局是一點一點的顯示出來,所以要不停的設置頂部布局 int topPadding = spance - headerHeight; switch (state) { case NONE: // 當用戶更下拉的時候狀態:提示下拉狀態 if (spance > 0) { state = PULL; } break; case PULL: topPadding(topPadding); // 用戶下拉超過一定並且處於滑動滾動的的時候:提示松開刷新狀態 if (spance > headerHeight + 20 && scorellStatep == SCROLL_STATE_TOUCH_SCROLL) { state = REFPULL; reflashViewBySate(); } break; case REFPULL: topPadding(topPadding); // 當用戶回滾到低於一定高度的時候:提示下拉刷新狀態 if (spance < headerHeight + 20) { state = PULL; reflashViewBySate(); } else if (spance <= 0) { state = NONE; isReflash = false; reflashViewBySate(); } } } /** * 根據狀態:在去決定是否刷新數據和加載布局 */ private void reflashViewBySate() { // 動畫效果 RotateAnimation animation = new RotateAnimation(0, 180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); animation.setDuration(500); animation.setFillAfter(true); // 動畫效果 RotateAnimation animation1 = new RotateAnimation(180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); animation1.setDuration(500); animation1.setFillAfter(true); switch (state) { case NONE: topPadding(-headerHeight); arrawImage.clearAnimation(); break; case PULL: arrawImage.setVisibility(View.VISIBLE); progressBar.setVisibility(View.GONE); stateMessage.setText("下拉可以刷新"); arrawImage.clearAnimation(); arrawImage.setAnimation(animation1); break; case REFPULL: arrawImage.setVisibility(View.VISIBLE); progressBar.setVisibility(View.GONE); stateMessage.setText("松開可以刷新"); arrawImage.clearAnimation(); arrawImage.setAnimation(animation); break; case LOADING: topPadding(50); progressBar.setVisibility(View.VISIBLE); arrawImage.setVisibility(View.GONE); stateMessage.setText("正在刷新..."); arrawImage.clearAnimation(); break; } } /** * 刷新完成之後,更改刷新時間 */ @SuppressLint("SimpleDateFormat") public void reflashComplete() { state = NONE; isReflash = false; reflashViewBySate(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss"); Date date = new Date(System.currentTimeMillis()); String time = sdf.format(date); lastUpdatTime.setText(time); } public interface IReflashLinster { public void reflash(); } public void setIReflashLinster(IReflashLinster iReflashLinster) { this.iReflashLinster = iReflashLinster; }
2.Maintivity 在主界面中的使用
package com.zengtao.pulltorefreshtest; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.Window; import android.widget.ArrayAdapter; import com.zengtao.refreshview.RefreshableView; import com.zengtao.refreshview.RefreshableView.IReflashLinster; public class MainActivity extends Activity implements IReflashLinster { private RefreshableView listView; private ArrayAdapterAdapter; private String[] str = { "傻逼才是王道 1", "傻逼才是王道 2", "text 3", "傻逼才是王道 4", "傻逼才是王道 5", "傻逼才是王道 6", "傻逼才是王道 7", "傻逼才是王道 8", "傻逼才是王道 9", "傻逼才是王道 10", "傻逼才是王道 11", "傻逼才是王道 12", "傻逼才是王道 13", "傻逼才是王道 14", "傻逼才是王道 1", "傻逼才是王道 2", "傻逼才是王道 3", "傻逼才是王道 4", "傻逼才是王道 5", "傻逼才是王道 6", "傻逼才是王道 7", "傻逼才是王道 8", "傻逼才是王道 9", "傻逼才是王道 10", "傻逼才是王道 11", "傻逼才是王道 12", "傻逼才是王道 13", "傻逼才是王道 14" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initView(); } private void initView() { listView = (RefreshableView) findViewById(R.id.listview); listView.setIReflashLinster(this); Adapter = new ArrayAdapter (this, android.R.layout.simple_list_item_1, str); listView.setAdapter(Adapter); } @Override public void reflash() { Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { } }, 3000); } }
寫在前面因為有這樣的一個場景,需要實現豎直方向的多色進度條,然後在網上也找了下,沒看到符合需要的,於是自定義了一個,效果如下: 具體實現本來想定義水平的,然後旋轉一下,後
前言想想我們常用的網易雲音樂,允許我們把歌詞連帶著歌曲的圖片拼在一起變成一張圖,我們再把這張圖片分享出去就好了。那麼,本篇的內容就是動手做一個帶文字的圖片。這裡也記錄下上
Android提供了實現按照秒計時的API,今天就是用這個API實現簡單的倒計時。來個布局: 對應活動中的代碼如下: pa
Android App框架設計之編寫基類BaseActivity編寫基類BaseActivity- OOP裡面子類裡面能夠共享父類的方法,提高代碼的可復用性- 基類的編寫
Dagger 是一種android平台的依賴注入框架,是有一家專注於移動