Android控制元件----關於上拉重新整理上拉載入的自定義控制元件
阿新 • • 發佈:2018-12-09
首先需要明白的是,平常用的ListView做不到類似於小說章節閱讀的瀏覽效果,去實現重新整理載入的功能。雖然GitHub上有一些開源庫可以使用,但是這種東西自己如果有時間能夠親歷一遍瞭解的更加透徹,畢竟在很多Android的APP中都有這方面的功能。話不多說,下面我們就開始上程式碼。
首先把頭部尾部的佈局弄好
headview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation ="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/head"
android:orientation="horizontal"
android:gravity ="center"
android:padding="5dp">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleInverse"
android:id="@+id/progressbar"/>
<TextView
android:layout_width ="wrap_content"
android:layout_height="wrap_content"
android:text="正在重新整理。。。。"
android:id="@+id/update_info"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/update_time"
/>
</LinearLayout>
</LinearLayout>
footview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/foot_load"
android:padding="5dp"
android:gravity="center">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyle"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="載入中。。。。"
/>
</LinearLayout>
</LinearLayout>
根據這2個介面佈局我們就可以去搭建一個自己的自定義ListView,以此來實現我們想要的效果
下面我們就可以著手自定義的ListView的編寫了
package com.yakir.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.example.t210_06.R;
import java.text.SimpleDateFormat;
/**
* 自定義listview實現上拉重新整理下拉載入
*/
public class MyListView extends ListView implements AbsListView.OnScrollListener{
private View footview;
private View headview;
private int totaItemCounts;
private int lasstVisible;
private int fistVisiable;
private LoadListener loadListener;
private int footViewHeight;
private int headViewHeight;
private int yload;
boolean isLoading;
private TextView updateInfo;
private TextView updateTime;
private ProgressBar progressBar;
public MyListView(Context context) {
super(context);
initView(context);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
//拿到頭佈局xml
headview=LayoutInflater.from(context).inflate(R.layout.headview,null);
updateInfo=(TextView)headview.findViewById(R.id.update_info);
updateTime=(TextView)headview.findViewById(R.id.update_time);
progressBar=(ProgressBar)headview.findViewById(R.id.progressbar);
updateTime.setText("更新於:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()));
//拿到尾佈局xml
footview=LayoutInflater.from(context).inflate(R.layout.footview,null);
//測量footview的高度
footview.measure(0,0);
//拿到高度
footViewHeight=footview.getMeasuredHeight();
//隱藏view
footview.setPadding(0,-footViewHeight,0,0);
headview.measure(0,0);
headViewHeight=headview.getMeasuredHeight();
headview.setPadding(0,-headViewHeight,0,0);
//設定不可見
// footview.findViewById(R.id.foot_load).setVisibility(View.GONE);
// headview.findViewById(R.id.head).setVisibility(View.GONE);
//新增到listview底部
this.addFooterView(footview);
//新增到listview頭部
this.addHeaderView(headview);
//設定拉動監聽
this.setOnScrollListener(this);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
yload=(int)ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveY=(int)ev.getY();
int paddingY=-headViewHeight+(moveY-yload)/2;
if (paddingY<0){
updateInfo.setText("下拉重新整理。。。");
progressBar.setVisibility(View.GONE);
}
if (paddingY>0){
updateInfo.setText("鬆開重新整理。。。");
progressBar.setVisibility(View.GONE);
}
headview.setPadding(0,paddingY,0,0);
break;
}
return super.onTouchEvent(ev);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (totaItemCounts==lasstVisible&&scrollState==SCROLL_STATE_IDLE) {
if (!isLoading) {
isLoading=true;
footview.setPadding(0,0,0,0);
//載入資料
loadListener.onLoad();
}
}
if (fistVisiable==0){
headview.setPadding(0,0,0,0);
updateInfo.setText("正在重新整理。。。");
progressBar.setVisibility(View.VISIBLE);
loadListener.pullLoad();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
this.fistVisiable=firstVisibleItem;
this.lasstVisible=firstVisibleItem+visibleItemCount;
this.totaItemCounts=totalItemCount;
}
//載入完成
public void loadComplete(){
isLoading=false;
footview.setPadding(0,-footViewHeight,0,0);
headview.setPadding(0,-headViewHeight,0,0);
}
public void setInterface(LoadListener loadListener){
this.loadListener=loadListener;
}
//介面回撥
public interface LoadListener{
void onLoad();
void pullLoad();
}
}
然後在外面的主介面佈局裡呼叫這個我們自己寫的外掛就行了
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.yakir.view.MyListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/list_view">
</com.yakir.view.MyListView>
</RelativeLayout>
MainActivity.java
package com.example.t210_06;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import com.yakir.view.MyListView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements MyListView.LoadListener{
private MyListView listview;
private List<Integer>list=new ArrayList<>();
private ArrayAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i=1;i<20;i++){
list.add(i);
}
initView();
adapter=new ArrayAdapter<>(this,android.R.layout.simple_expandable_list_item_1,list);
listview.setAdapter(adapter);
}
private void initView() {
listview=(MyListView) findViewById(R.id.list_view);
listview.setInterface(this);
}
@Override
public void onLoad() {
//設定三秒延遲模仿延時獲取資料
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//載入資料
for (int j=1;j<11;j++){
list.add(j);
}
//更新 資料
adapter.notifyDataSetChanged();
//載入完畢
listview.loadComplete();
}
},3000);
}
@Override
public void pullLoad() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
list.clear();
for (int i=1;i<20;i++){
list.add(i+1);
}
adapter.notifyDataSetChanged();
listview.loadComplete();
}
},2000);
}
}
這1點必須注意: 在initView(context)方法中通過LayoutInfalter.from(context).from(你的xml,null);拿到xml。返回一個View物件,ListView中有一個setfootView()方法,使用他可以設定View到ListView的底部,當然做了這兩步是完全不夠的,我們還需要對這個View做一個互動的操作,當用戶滑到底部時這個View顯示,資料載入完畢之後這個View消失。這裡就能通過設定底部檢視的焦點位置去,使其隱藏,當下拉的時候觸發事件就可以達到我們的效果。