English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
1.추가 로드 더 레이아웃
1_초기화 및 숨기기 코드
RefreshListView 생성자 메서드에서 호출
private void initFooterView(Context context) { View footerView = View.inflate(context, R.layout.refresh_listview_footer, null); //숨기기 코드 footerView.measure(0, 0); int footerViewHeight = footerView.getMeasuredHeight(); footerView.setPadding(0, -footerViewHeight, 0, 0); this.addFooterView(footerView); }
2_뷰어 파일 refresh_listview_footer.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:gravity="center" android:orientation="horizontal" > <ProgressBar android:layout_margin="5dip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:indeterminateDrawable="@drawable/custom_progressbar" /> <TextView android:layout_marginLeft="10dip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="로딩 중..." android:textColor="#ff0000" android:textSize="25sp" /> </LinearLayout>
2. 아래로 끌어당겼을 때
/** * 메뉴 페이지에 해당하는 뉴스 페이지 태그 페이지 * 총12개 * @author Administrator * */ public class TabMenuDetailPager extends MenuDetailBasePager implements OnPageChangeListener { /** * 뉴스 센터-뉴스 메뉴에 해당하는 태그에 대한 데이터 */ private NewCenterTag newCenterTag; ..................... /** * 데이터 더 로드할 URL */ private String moreUrl; /** * 데이터 더 로드 중인지 여부 */ protected boolean isLoadingMore = false; ................... @Override public View initView() { View view = View.inflate(mActivity, R.layout.tab_detail, null); //View를 XUtils 프레임워크에 주입합니다. ViewUtils.inject(this, view); .......................... //설정下拉페이지 리프레시 리스너 mListView.setOnRefreshListener(new OnRefreshListener() { @Override public void onPullDownRefresh() {}} isPullDownRefreshing = true; getDataFromNet(); } @Override public void onLoadingMore() { if(TextUtils.isEmpty(moreUrl)){ Toast.makeText(mActivity, "데이터가 더 없습니다.", 1).show(); mListView.onRefreshFinish(false); }else{ //데이터가 더 있으며, 더 많은 데이터를 로드하려고 합니다. getMoreDataFromNet(); } } }); return view; } /** * 데이터 로드 */ protected void getMoreDataFromNet() { HttpUtils httpUtils = new HttpUtils(); httpUtils.send(HttpMethod.GET, moreUrl, new RequestCallBack<String>() { @Override public void onSuccess(ResponseInfo<String> responseInfo) { System.out.println("데이터 로드 성공: ");+responseInfo.result); mListView.onRefreshFinish(false); isLoadingMore = true; processData(responseInfo.result); } @Override public void onFailure(HttpException error, String msg) { mListView.onRefreshFinish(false); System.out.println("데이터 로드 실패: ");+ msg); } }); } /** * json 데이터 처리 및 해석 * @param json */ protected void processData(String json) { TabDetailBean bean = parserJson(json); if(!isLoadingMore){ System.out.println(bean.data.news.get(0).title); topnews = bean.data.topnews; //ViewPager에 어댑터 설정 TabDetailAdapter adapter = new TabDetailAdapter(); mViewPager.setAdapter(adapter); // 모든 뷰를 지우습니다 ll_point_group.removeAllViews(); for(int i=0;i<topnews.size();i++{ View point = new View(mActivity); LayoutParams params = new LayoutParams(5, 5) ; point.setBackgroundResource(R.drawable.tab_detail_point_bg); if(i!=0){ params.leftMargin = 10; } point.setEnabled(false); point.setLayoutParams(params); ll_point_group.addView(point); } previousPointPosition = 0; //기본 이미지 설명과 가이드 포인트를 설정합니다 mtv_title_description.setText(topnews.get(previousPointPosition).title); ll_point_group.getChildAt(previousPointPosition).setEnabled(true); //페이지 변경을 감지하는 리스너를 설정합니다 mViewPager.setOnPageChangeListener(this); //어댑터와 데이터를 설정합니다 newsLists = bean.data.news; listViewAdapter = new ListViewAdapter(); mListView.setAdapter(listViewAdapter); // mListView.addHeaderView(v) ;//뷰를 ListView에 추가하는 방식으로 한 개의 뷰를 추가합니다 }else{ //데이터를 로드한 이전 셋에 목록 뉴스를 가져와서 데이터를 새로운 데이터로 업데이트합니다 isLoadingMore = false; List<News>moreDataNews = bean.data.news; newsLists.addAll(moreDataNews); listViewAdapter.notifyDataSetChanged();//데이터 새로고침 } } ................ /** * 용 Gson 오픈 소스 프로젝트 json을 분석합니다 * @param json */ private TabDetailBean parserJson(String json) { Gson gson = new Gson(); TabDetailBean bean = gson.fromJson(json, TabDetailBean.class); moreUrl = bean.data.more; if(TextUtils.isEmpty(moreUrl)){ moreUrl = null; }else{ moreUrl = ConstantUtils.server_url+moreUrl; } return bean; } @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } ............... }
3.完整代码
package com.atguigu.refreshlistview; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.widget.AbsListView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import java.text.SimpleDateFormat; import java.util.Date; /** * 功能:自定义下拉刷新的ListView */ public class RefreshListview extends ListView { /** * 下拉刷新和顶部轮播图 */ private LinearLayout headerView; /** * 위下达시 새로고침 컨트롤 */ private View ll_pull_down_refresh; private ImageView iv_arrow; private ProgressBar pb_status; private TextView tv_status; private TextView tv_time; /** * 下拉刷新控件的高 */ private int pullDownRefreshHeight; /** * 下拉刷新 */ public static final int PULL_DOWN_REFRESH = 0; /** * 手松刷新 */ public static final int RELEASE_REFRESH = 1; /** * 正在刷新 */ public static final int REFRESHING = 2; /** * 当前状态 */ private int currentStatus = PULL_DOWN_REFRESH; private Animation upAnimation; private Animation downAnimation; /** * 加载更多的控件 */ private View footerView; /** * 加载更多控件高 */ private int footerViewHeight; /** * 是否已经加载更多 */ private boolean isLoadMore = false; /** * 顶部轮播图部分 */ private View topNewsView; /** * ListView在Y轴上的坐标 */ private int listViewOnScreenY = -1; public RefreshListview(Context context) { this(context, null); } public RefreshListview(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RefreshListview(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initHeaderView(context); initAnimation(); initFooterView(context); } private void initFooterView(Context context) { footerView = View.inflate(context, R.layout.refresh_footer, null); footerView.measure(0, 0); footerViewHeight = footerView.getMeasuredHeight(); footerView.setPadding(0, -footerViewHeight, 0, 0); //ListView에 푸터 추가 addFooterView(footerView); //ListView의 스크롤을 감지합니다 setOnScrollListener(new MyOnScrollListener()); } /** * 헤더 뷰에 톱 뉴스 뷰 추가 * @param topNewsView */ public void addTopNewsView(View topNewsView) { if(topNewsView != null){ this.topNewsView =topNewsView; headerView.addView(topNewsView); } } class MyOnScrollListener implements OnScrollListener{ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { //정지 상태나 진동 롤링 시 if(scrollState ==OnScrollListener.SCROLL_STATE_IDLE||scrollState ==OnScrollListener.SCROLL_STATE_FLING){ //그리고 마지막으로 보이는 항목입니다 if(getLastVisiblePosition()>=getCount())-1{ //1.데이터 더 로드 레이아웃을 표시합니다}} footerView.setPadding(8,8,8,8); //2.상태 변경 isLoadMore = true; //3.호출 인터페이스 if(mOnRefreshListener != null){ mOnRefreshListener.onLoadMore(); } } } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } } private void initAnimation() { upAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); upAnimation.setDuration(500); upAnimation.setFillAfter(true); downAnimation = new RotateAnimation(-180, -360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); downAnimation.setDuration(500); downAnimation.setFillAfter(true); } private void initHeaderView(Context context) { headerView = (LinearLayout) View.inflate(context, R.layout.refresh_header, null); //위下达시 새로고침 컨트롤 ll_pull_down_refresh = headerView.findViewById(R.id.ll_pull_down_refresh); iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow); pb_status = (ProgressBar) headerView.findViewById(R.id.pb_status); tv_status = (TextView) headerView.findViewById(R.id.tv_status); tv_time = (TextView) headerView.findViewById(R.id.tv_time); //측정 ll_pull_down_refresh.measure(0, 0); pullDownRefreshHeight = ll_pull_down_refresh.getMeasuredHeight(); //기본적으로下拉刷新 컨트롤을 숨깁니다 // View.setPadding(0,-控件高,0,0);//完全隐藏 //View.setPadding(0, 0, 0, 0);//完全显示 ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0); //리스트뷰의 헤더 추가 addHeaderView(headerView); } private float startY = -1; @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: //1. 시작 좌표 기록 startY = ev.getY(); break; case MotionEvent.ACTION_MOVE: if (startY == -1) { startY = ev.getY(); } //상단 슬라이드 쇼가 완전히 표시되었는지 확인합니다. 완전히 표시되면下拉刷新가 가능합니다 boolean isDisplayTopNews = isDisplayTopNews(); if(!isDisplayTopNews){ //加载更多 break; } //현재가 새로고침 중이면, 다시 새로고침하지 않게 하세요 if (currentStatus == REFRESHING) { break; } //2. 새로운 좌표로 오다 float endY = ev.getY(); //3. 슬라이딩 거리 기록 float distanceY = endY - startY; if (distanceY > 0) {//下拉 //int paddingTop = -컨트롤 높이 + distanceY; int paddingTop = (int) (-pullDownRefreshHeight + distanceY); if (paddingTop < 0 && currentStatus != PULL_DOWN_REFRESH) { //下拉刷新 상태 currentStatus = PULL_DOWN_REFRESH; //更新状态 refreshViewState(); } else if (paddingTop > 0 && currentStatus != RELEASE_REFRESH) { //손을 떼면 갱신 상태 currentStatus = RELEASE_REFRESH; //更新状态 refreshViewState(); } ll_pull_down_refresh.setPadding(0, paddingTop, 0, 0); //View.setPadding(0,paddingTop,0,0);//动态的显示下拉刷新控件 } break; case MotionEvent.ACTION_UP: startY = -1; if (currentStatus == PULL_DOWN_REFRESH) { // View.setPadding(0,-控件高,0,0);//完全隐藏 ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0); } else if (currentStatus == RELEASE_REFRESH) { //设置状态为正在刷新 currentStatus = REFRESHING; refreshViewState(); // View.setPadding(0,0,0,0);//完全显示 ll_pull_down_refresh.setPadding(0, 0, 0, 0); //回调接口 if (mOnRefreshListener != null) { mOnRefreshListener.onPullDownRefresh(); } } break; } return super.onTouchEvent(ev); } /** * 判断是否完全显示顶部轮播图 * 当ListView在屏幕上的Y轴坐标小于或者等于顶部轮播图在Y轴的坐标的时候,顶部轮播图完全显示 * @return */ private boolean isDisplayTopNews() { if(topNewsView != null){ //1.得到ListView在屏幕上的坐标 int[] location = new int[2]; if(listViewOnScreenY == -1{ getLocationOnScreen(location); listViewOnScreenY = location[1]; } //2.得到顶部轮播图在屏幕上的坐标 topNewsView.getLocationOnScreen(location); int topNewsViewOnScreenY = location[1]; // if(listViewOnScreenY <= topNewsViewOnScreenY){ // return true; // }else{ // return false; // } return listViewOnScreenY <= topNewsViewOnScreenY; }else{ return true; } } private void refreshViewState() { switch (currentStatus) { case PULL_DOWN_REFRESH://下拉刷新 상태 iv_arrow.startAnimation(downAnimation); tv_status.setText("下拉刷新..."); break; case RELEASE_REFRESH://손을 떼면 갱신 상태 iv_arrow.startAnimation(upAnimation); tv_status.setText("손을 떼면 갱신..."); break; case REFRESHING://refreshing 상태 tv_status.setText("正在刷新..."); pb_status.setVisibility(VISIBLE); iv_arrow.clearAnimation(); iv_arrow.setVisibility(GONE); break; } } /** * 인터넷 연결 성공과 실패할 때 이 메서드를 콜백합니다 * 사용자가 갱신 상태를 원복합니다 * * @param sucess */ public void onRefreshFinish(boolean sucess) { if(isLoadMore){ //加载更多 isLoadMore = false; //加载更多布局 숨기기 footerView.setPadding(0,-footerViewHeight,0,0); }else{ //下拉刷新 tv_status.setText("下拉刷新..."); currentStatus = PULL_DOWN_REFRESH; iv_arrow.clearAnimation(); pb_status.setVisibility(GONE); iv_arrow.setVisibility(VISIBLE); //下拉刷新控件 숨기기 ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0); if (sucess) { //최신 업데이트 시간 설정 tv_time.setText("최근 업데이트 시간:" + getSystemTime()); } } } /** * 현재 Android 시스템 시간을 얻습니다 * * @return */ private String getSystemTime() { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return format.format(new Date()); } /** * 컨트롤러의 새로 고침을 감시합니다 */ public interface OnRefreshListener { /** * 下拉刷新 시 이 메서드를 콜백합니다 */ public void onPullDownRefresh(); /** 더 많은 데이터를 로드할 때 이 메서드를 콜백합니다 */ public void onLoadMore(); } private OnRefreshListener mOnRefreshListener; /** * 감시를 설정합니다. 외부에서 설정됩니다 */ public void setOnRefreshListener(OnRefreshListener l) { this.mOnRefreshListener = l; } }
위 내용은 편집자가 여러분에게 소개한 Android 모방 실리콘 밸리 뉴스下拉刷新입니다./위 내용은 저가 여러분에게 소개한 Android 모방 실리콘 밸리 뉴스下拉刷新입니다. 더 많은 도움이 되길 바랍니다. 여러분이 어떤 질문이나 의문이 있으면, 댓글을 남겨 주시면, 편집자가 즉시 답변을 드리겠습니다. 또한, 여러분의 지원에 깊이 감사드립니다!
선언: 본문은 인터넷에서 가져왔으며, 저작권자는 본사이며, 인터넷 사용자가 자발적으로 기여하고 자신의 파일을 업로드한 것입니다. 사이트는 소유권을 가지지 않으며, 인공 편집 처리를 하지 않으며, 관련 법적 책임을 부담하지 않습니다. 저작권 침해 내용이 있을 경우, 이메일을 notice#w로 보내 주시기 바랍니다.3codebox.com(이메일을 보내면, #을 @으로 변경하십시오. 신고하고 관련 증거를 제공하시면, 사이트는 즉시 저작권 침해 내용을 삭제합니다.