From afb62b49b79a31ab62a548f9cef672dfc9bae16f Mon Sep 17 00:00:00 2001 From: wjc <1243177876@qq.com> Date: 星期三, 09 四月 2025 09:04:38 +0800 Subject: [PATCH] 2025年04月09日09:04:34 --- app/src/main/res/mipmap-xhdpi/loading_14.png | 0 app/src/main/res/mipmap-xhdpi/loading_1.png | 0 app/src/main/res/drawable/loading_44.png | 0 app/src/main/res/mipmap-xhdpi/loading_31.png | 0 app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/NestedScrollLayout.java | 152 +++ app/src/main/java/com/hdl/photovoltaic/widget/LoadingDialog.java | 4 app/src/main/res/mipmap-xhdpi/loading_22.png | 0 app/src/main/res/mipmap-xhdpi/loading_21.png | 0 app/src/main/res/mipmap-xhdpi/loading_39.png | 0 app/src/main/res/mipmap-xhdpi/loading_13.png | 0 app/src/main/res/mipmap-xhdpi/loading_2.png | 0 app/src/main/res/mipmap-xhdpi/loading_30.png | 0 app/src/main/res/mipmap-xhdpi/loading_12.png | 0 app/build.gradle | 3 app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/HDLRefreshView.java | 127 ++ app/src/main/res/drawable/loading_refresh.xml | 136 ++ app/src/main/res/mipmap-xhdpi/loading_38.png | 0 app/src/main/res/mipmap-xhdpi/loading_41.png | 0 app/src/main/res/mipmap-xhdpi/loading_4.png | 0 app/src/main/res/layout/view_refresh_header.xml | 29 app/src/main/res/mipmap-xhdpi/loading_24.png | 0 app/src/main/res/mipmap-xhdpi/loading_11.png | 0 app/src/main/res/mipmap-xhdpi/loading_37.png | 0 app/src/main/res/mipmap-xhdpi/loading_40.png | 0 app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshLayout.java | 923 ++++++++++++++++++ app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseAndDeviceFragment.java | 14 app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshViewHolder.java | 345 +++++++ app/src/main/res/drawable-xhdpi/loading_gif.gif | 0 app/src/main/res/mipmap-xhdpi/loading_18.png | 0 app/src/main/res/mipmap-xhdpi/loading_3.png | 0 app/src/main/res/mipmap-xhdpi/loading_10.png | 0 app/src/main/res/mipmap-xhdpi/loading_23.png | 0 app/src/main/res/mipmap-xhdpi/loading_36.png | 0 app/src/main/res/mipmap-xhdpi/loading_27.png | 0 app/src/main/res/mipmap-xhdpi/loading_6.png | 0 app/src/main/res/mipmap-xhdpi/loading_19.png | 0 app/src/main/res/mipmap-xhdpi/loading_44.png | 0 app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGAStickyNavLayout.java | 520 ++++++++++ app/src/main/res/mipmap-xhdpi/loading_7.png | 0 app/src/main/res/mipmap-xhdpi/loading_35.png | 0 app/src/main/res/mipmap-xhdpi/loading_5.png | 0 app/src/main/res/mipmap-xhdpi/loading_26.png | 0 app/src/main/java/com/hdl/photovoltaic/ui/home/HomePageFragment.java | 80 + app/src/main/res/layout/fragment_home_page.xml | 20 app/src/main/res/mipmap-xhdpi/loading_43.png | 0 app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/HDLRefreshViewHolder.java | 131 ++ app/src/main/res/mipmap-xhdpi/loading_17.png | 0 app/src/main/res/mipmap-xhdpi/loading_42.png | 0 app/src/main/res/mipmap-xhdpi/loading_29.png | 0 app/src/main/res/mipmap-xhdpi/loading_25.png | 0 app/src/main/res/mipmap-xhdpi/loading_34.png | 0 app/src/main/res/mipmap-xhdpi/loading_33.png | 0 app/src/main/res/drawable/loading_gif.png | 0 app/src/main/res/mipmap-xhdpi/loading_16.png | 0 app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshScrollingUtil.java | 292 +++++ app/src/main/res/mipmap-xhdpi/loading_20.png | 0 app/src/main/res/mipmap-xhdpi/loading_9.png | 0 app/src/main/res/mipmap-xhdpi/loading_32.png | 0 app/src/main/res/drawable/loading_refresh_end.xml | 138 ++ app/src/main/res/mipmap-xhdpi/loading_28.png | 0 app/src/main/res/mipmap-xhdpi/loading_15.png | 0 app/src/main/res/mipmap-xhdpi/loading_8.png | 0 62 files changed, 2,894 insertions(+), 20 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 79af1d0..53caeb2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -157,6 +157,7 @@ // implementation 'com.hdl.android:debugsdk:1.0.71' implementation project(path: ':sdk') implementation 'androidx.activity:activity:1.2.3' + implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' @@ -206,13 +207,13 @@ //鍒嗘瀽鍜岀敤鎴锋爣绛剧瓑鍔熻兘(鍙�夛紝闆嗘垚鏋佸厜鍒嗘瀽SDK鍚庯紝鍗冲彲鏀寔琛屼负瑙﹀彂鎺ㄩ�佹秷鎭�佹帹閫佽浆鍖栫巼缁熻锛岀敤鎴疯涓哄垎) implementation 'cn.jiguang.sdk:joperate:2.0.2' - //鑻ヤ笉闆嗘垚鍘傚晢閫氶亾锛屽彲鐩存帴璺宠繃浠ヤ笅渚濊禆 // 鏋佸厜鍘傚晢鎻掍欢鐗堟湰涓庢帴鍏� JPush 鐗堟湰淇濇寔涓�鑷达紝涓嬪悓 // 鎺ュ叆鍗庝负鍘傚晢 implementation 'com.huawei.hms:push:6.9.0.300' implementation 'cn.jiguang.sdk.plugin:huawei:5.0.3' implementation 'com.huawei.agconnect:agconnect-core:1.9.1.301' + // // 鎺ュ叆 FCM 鍘傚晢 // implementation 'com.google.firebase:firebase-messaging:23.1.2' // implementation 'cn.jiguang.sdk.plugin:fcm:5.0.3' diff --git a/app/src/main/java/com/hdl/photovoltaic/ui/home/HomePageFragment.java b/app/src/main/java/com/hdl/photovoltaic/ui/home/HomePageFragment.java index 0469a3c..fb3783c 100644 --- a/app/src/main/java/com/hdl/photovoltaic/ui/home/HomePageFragment.java +++ b/app/src/main/java/com/hdl/photovoltaic/ui/home/HomePageFragment.java @@ -8,6 +8,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.location.LocationManager; +import android.os.AsyncTask; import android.os.Bundle; import android.provider.Settings; import android.text.TextUtils; @@ -16,7 +17,6 @@ import androidx.annotation.NonNull; import androidx.appcompat.content.res.AppCompatResources; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.bigkoo.pickerview.builder.TimePickerBuilder; import com.bigkoo.pickerview.listener.OnTimeSelectListener; @@ -55,6 +55,8 @@ import com.hdl.photovoltaic.utils.TimeUtils; import com.hdl.photovoltaic.widget.ConfirmationCancelDialog; import com.hdl.photovoltaic.widget.FlashingBoxDialog; +import com.hdl.photovoltaic.widget.refreshlayout.BGARefreshLayout; +import com.hdl.photovoltaic.widget.refreshlayout.HDLRefreshViewHolder; import com.hdl.sdk.link.core.bean.eventbus.BaseEventBus; import org.greenrobot.eventbus.EventBus; @@ -70,7 +72,7 @@ * 棣栭〉妯″潡 */ -public class HomePageFragment extends CustomBaseFragment implements AAChartView.AAChartViewCallBack { +public class HomePageFragment extends CustomBaseFragment implements AAChartView.AAChartViewCallBack, BGARefreshLayout.BGARefreshLayoutDelegate { FragmentHomePageBinding viewBinding; @@ -342,15 +344,14 @@ } }); //璁剧疆涓嬫媺绠ご棰滆壊 - viewBinding.srl.setColorSchemeResources(R.color.text_FF245EC3); - viewBinding.srl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { - @Override - public void onRefresh() { - viewBinding.srl.setRefreshing(false); - readDate(); - } - }); - +// viewBinding.rsl.setColorSchemeResources(R.color.text_FF245EC3); +// viewBinding.rsl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { +// @Override +// public void onRefresh() { +// viewBinding.rsl.setRefreshing(false); +// readDate(); +// } +// }); } @@ -466,8 +467,18 @@ viewBinding.homePageStationSelectTimeLl.setVisibility(View.VISIBLE); viewBinding.autoSizeMyAAChart.setBackgroundColor(_mActivity.getColor(R.color.text_FF1C1C1E)); setUpAAChartView(true);//鍥捐〃鍔犺浇 + processLogic(); + } + protected void processLogic() { + viewBinding.rsl.setDelegate(this); + HDLRefreshViewHolder hdlRefreshViewHolder = new HDLRefreshViewHolder(_mActivity, true); + hdlRefreshViewHolder.setPullDownImageResource(R.mipmap.loading_44); + hdlRefreshViewHolder.setChangeToReleaseRefreshAnimResId(R.drawable.loading_refresh); + hdlRefreshViewHolder.setRefreshingAnimResId(R.drawable.loading_refresh_end); + viewBinding.rsl.setRefreshViewHolder(hdlRefreshViewHolder); + } @Override public void chartViewDidFinishLoad(AAChartView aaChartView) { @@ -501,7 +512,7 @@ * 鐢电珯鐘舵�佹瑙� */ private void getStatusOverview() { - HdlResidenceLogic.getInstance().getStatusOverview("","","",new CloudCallBeak<StatusOverviewBean>() { + HdlResidenceLogic.getInstance().getStatusOverview("", "", "", new CloudCallBeak<StatusOverviewBean>() { @Override public void onSuccess(StatusOverviewBean statusOverviewBean) { if (statusOverviewBean == null) { @@ -726,4 +737,49 @@ } } + + @Override + public void onBGARefreshLayoutBeginRefreshing(BGARefreshLayout refreshLayout) { + new AsyncTask<Void, Void, Void>() { + + @Override + protected Void doInBackground(Void... params) { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + viewBinding.rsl.endRefreshing(); + //鍔犺浇鏈�鏂版暟鎹畬鎴� + readDate(); + } + }.execute(); + } + + @Override + public boolean onBGARefreshLayoutBeginLoadingMore(BGARefreshLayout refreshLayout) { + new AsyncTask<Void, Void, Void>() { + + @Override + protected Void doInBackground(Void... params) { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + viewBinding.rsl.endLoadingMore(); + } + }.execute(); + return true; + } } diff --git a/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseAndDeviceFragment.java b/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseAndDeviceFragment.java index ac38b08..4d7c7e4 100644 --- a/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseAndDeviceFragment.java +++ b/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseAndDeviceFragment.java @@ -162,6 +162,9 @@ viewBinding.allLl.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + if (powerStationStatusValue.equals(PowerStationStatus.All)) { + return; + } powerStationStatusValue = PowerStationStatus.All; viewBinding.allLl.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.station_status_yes_ffffff)); viewBinding.faultsLl.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.station_status_no_ffffff)); @@ -180,6 +183,9 @@ viewBinding.faultsLl.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + if (powerStationStatusValue.equals(PowerStationStatus.malfunction)) { + return; + } powerStationStatusValue = PowerStationStatus.malfunction; viewBinding.allLl.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.station_status_no_ffffff)); viewBinding.faultsLl.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.station_status_yes_ffffff)); @@ -198,6 +204,9 @@ viewBinding.offlineLl.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + if (powerStationStatusValue.equals(PowerStationStatus.off)) { + return; + } powerStationStatusValue = PowerStationStatus.off; viewBinding.allLl.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.station_status_no_ffffff)); viewBinding.faultsLl.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.station_status_no_ffffff)); @@ -216,6 +225,9 @@ viewBinding.connectedLl.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + if (powerStationStatusValue.equals(PowerStationStatus.connecting)) { + return; + } powerStationStatusValue = PowerStationStatus.connecting; viewBinding.allLl.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.station_status_no_ffffff)); viewBinding.faultsLl.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.station_status_no_ffffff)); @@ -765,7 +777,7 @@ * 鐢电珯鐘舵�佹瑙� */ private void getStatusOverview() { - HdlResidenceLogic.getInstance().getStatusOverview(screeningConditionStatus,installedCapacityMinValue,installedCapacityMaxValue,new CloudCallBeak<StatusOverviewBean>() { + HdlResidenceLogic.getInstance().getStatusOverview(screeningConditionStatus, installedCapacityMinValue, installedCapacityMaxValue, new CloudCallBeak<StatusOverviewBean>() { @Override public void onSuccess(StatusOverviewBean statusOverviewBean) { if (statusOverviewBean == null) { diff --git a/app/src/main/java/com/hdl/photovoltaic/widget/LoadingDialog.java b/app/src/main/java/com/hdl/photovoltaic/widget/LoadingDialog.java index 677ad65..a4d020d 100644 --- a/app/src/main/java/com/hdl/photovoltaic/widget/LoadingDialog.java +++ b/app/src/main/java/com/hdl/photovoltaic/widget/LoadingDialog.java @@ -1,8 +1,6 @@ package com.hdl.photovoltaic.widget; -import android.app.Dialog; import android.content.Context; -import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.text.TextUtils; import android.view.WindowManager; @@ -39,7 +37,7 @@ getWindow().setAttributes(params); Glide.with(context) // .asBitmap() // 寮哄埗浣滀负闈欐�佸浘鐗囧姞杞� - .load(R.drawable.loading) + .load(R.drawable.loading_gif) .into(imageView); // content.setText(R.string.device_鍔犺浇涓�); } diff --git a/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshLayout.java b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshLayout.java new file mode 100644 index 0000000..2e354af --- /dev/null +++ b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshLayout.java @@ -0,0 +1,923 @@ +/** + * Copyright 2015 bingoogolapple + * <p/> + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hdl.photovoltaic.widget.refreshlayout; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.webkit.WebView; +import android.widget.AbsListView; +import android.widget.LinearLayout; +import android.widget.ScrollView; + +import androidx.recyclerview.widget.RecyclerView; + + + +import java.lang.reflect.Field; + +/** + * 浣滆��:鐜嬫旦 閭欢:bingoogolapple@gmail.com + * 鍒涘缓鏃堕棿:15/5/21 22:35 + * 鎻忚堪:涓嬫媺鍒锋柊銆佷笂鎷夊姞杞芥洿澶氥�佸彲娣诲姞鑷畾涔夛紙鍥哄畾銆佸彲婊戝姩锛夊ご閮ㄦ帶浠讹紙渚嬪鎱曡缃慳pp椤堕儴鐨勫箍鍛婁綅锛� + */ +public class BGARefreshLayout extends LinearLayout { + private static final String TAG = BGARefreshLayout.class.getSimpleName(); + + private BGARefreshViewHolder mRefreshViewHolder; + /** + * 鏁翠釜澶撮儴鎺т欢锛屼笅鎷夊埛鏂版帶浠秏RefreshHeaderView鍜屼笅鎷夊埛鏂版帶浠朵笅鏂圭殑鑷畾涔夌粍浠秏CustomHeaderView鐨勭埗鎺т欢 + */ + private LinearLayout mWholeHeaderView; + /** + * 涓嬫媺鍒锋柊鎺т欢 + */ + private View mRefreshHeaderView; + /** + * 涓嬫媺鍒锋柊鎺т欢涓嬫柟鐨勮嚜瀹氫箟鎺т欢 + */ + private View mCustomHeaderView; + /** + * 涓嬫媺鍒锋柊鎺т欢涓嬫柟鐨勮嚜瀹氫箟鎺т欢鏄惁鍙粴鍔紝榛樿涓嶅彲婊氬姩 + */ + private boolean mIsCustomHeaderViewScrollable = false; + /** + * 涓嬫媺鍒锋柊鎺т欢鐨勯珮搴� + */ + private int mRefreshHeaderViewHeight; + /** + * 褰撳墠鍒锋柊鐘舵�� + */ + private RefreshStatus mCurrentRefreshStatus = RefreshStatus.IDLE; + /** + * 涓婃媺鍔犺浇鏇村鎺т欢 + */ + private View mLoadMoreFooterView; + /** + * 涓婃媺鍔犺浇鏇村鎺т欢鐨勯珮搴� + */ + private int mLoadMoreFooterViewHeight; + /** + * 涓嬫媺鍒锋柊鍜屼笂鎷夊姞杞芥洿澶氫唬鐞� + */ + private BGARefreshLayoutDelegate mDelegate; + /** + * 鎵嬫寚鎸変笅鏃讹紝y杞存柟鍚戠殑鍋忕Щ閲� + */ + private int mWholeHeaderDownY = -1; + /** + * 鏁翠釜澶撮儴鎺т欢鏈�灏忕殑paddingTop + */ + private int mMinWholeHeaderViewPaddingTop; + /** + * 鏁翠釜澶撮儴鎺т欢鏈�澶х殑paddingTop + */ + private int mMaxWholeHeaderViewPaddingTop; + + /** + * 鏄惁澶勪簬姝e湪鍔犺浇鏇村鐘舵�� + */ + private boolean mIsLoadingMore = false; + + private AbsListView mAbsListView; + private ScrollView mScrollView; + private RecyclerView mRecyclerView; + private View mNormalView; + private WebView mWebView; + private BGAStickyNavLayout mStickyNavLayout; + private NestedScrollLayout mNestedScrollLayout; + private View mContentView; + + private float mInterceptTouchDownX = -1; + private float mInterceptTouchDownY = -1; + /** + * 鎸変笅鏃舵暣涓ご閮ㄦ帶浠剁殑paddingTop + */ + private int mWholeHeaderViewDownPaddingTop = 0; + /** + * 璁板綍寮�濮嬩笅鎷夊埛鏂版椂鐨刣ownY + */ + private int mRefreshDownY = -1; + + /** + * 鏄惁宸茬粡璁剧疆鍐呭鎺т欢婊氬姩鐩戝惉鍣� + */ + private boolean mIsInitedContentViewScrollListener = false; + /** + * 瑙﹀彂涓婃媺鍔犺浇鏇村鏃舵槸鍚︽樉绀哄姞杞芥洿澶氭帶浠� + */ + private boolean mIsShowLoadingMoreView = true; + + /** + * 涓嬫媺鍒锋柊鏄惁鍙敤 + */ + private boolean mPullDownRefreshEnable = true; + + private Handler mHandler; + + private BGARefreshScaleDelegate mRefreshScaleDelegate; + + private int mTouchSlop; + + public BGARefreshLayout(Context context) { + this(context, null); + } + + public BGARefreshLayout(Context context, AttributeSet attrs) { + super(context, attrs); + setOrientation(LinearLayout.VERTICAL); + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + mHandler = new Handler(Looper.getMainLooper()); + initWholeHeaderView(); + } + + /** + * 鍒濆鍖栨暣涓ご閮ㄦ帶浠� + */ + private void initWholeHeaderView() { + mWholeHeaderView = new LinearLayout(getContext()); + mWholeHeaderView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + mWholeHeaderView.setOrientation(LinearLayout.VERTICAL); + addView(mWholeHeaderView); + } + + @Override + public void onFinishInflate() { + super.onFinishInflate(); + + if (getChildCount() != 2) { + throw new RuntimeException(BGARefreshLayout.class.getSimpleName() + "蹇呴』鏈変笖鍙湁涓�涓瓙鎺т欢"); + } + + mContentView = getChildAt(1); + if (mContentView instanceof AbsListView) { + mAbsListView = (AbsListView) mContentView; + } else if (mContentView instanceof RecyclerView) { + mRecyclerView = (RecyclerView) mContentView; + } else if (mContentView instanceof ScrollView) { + mScrollView = (ScrollView) mContentView; + } else if (mContentView instanceof WebView) { + mWebView = (WebView) mContentView; + } else if (mContentView instanceof BGAStickyNavLayout) { + mStickyNavLayout = (BGAStickyNavLayout) mContentView; + mStickyNavLayout.setRefreshLayout(this); + } else if (mContentView instanceof NestedScrollLayout) { + mNestedScrollLayout = (NestedScrollLayout) mContentView; + } else { + mNormalView = mContentView; + // 璁剧疆涓哄彲鐐瑰嚮锛屽惁鍒欏湪绌虹櫧鍖哄煙鏃犳硶鎷栧姩 + mNormalView.setClickable(true); + } + } + + public void setRefreshViewHolder(BGARefreshViewHolder refreshViewHolder) { + mRefreshViewHolder = refreshViewHolder; + mRefreshViewHolder.setRefreshLayout(this); + initRefreshHeaderView(); + initLoadMoreFooterView(); + } + + public void startChangeWholeHeaderViewPaddingTop(int distance) { + ValueAnimator animator = ValueAnimator.ofInt(mWholeHeaderView.getPaddingTop(), mWholeHeaderView.getPaddingTop() - distance); + animator.setDuration(mRefreshViewHolder.getTopAnimDuration()); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + int paddingTop = (int) animation.getAnimatedValue(); + mWholeHeaderView.setPadding(0, paddingTop, 0, 0); + } + }); + animator.start(); + } + + /** + * 鍒濆鍖栦笅鎷夊埛鏂版帶浠� + * + * @return + */ + private void initRefreshHeaderView() { + mRefreshHeaderView = mRefreshViewHolder.getRefreshHeaderView(); + if (mRefreshHeaderView != null) { + mRefreshHeaderView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + + mRefreshHeaderViewHeight = mRefreshViewHolder.getRefreshHeaderViewHeight(); + mMinWholeHeaderViewPaddingTop = -mRefreshHeaderViewHeight; + mMaxWholeHeaderViewPaddingTop = (int) (mRefreshHeaderViewHeight * mRefreshViewHolder.getSpringDistanceScale()); + + mWholeHeaderView.setPadding(0, mMinWholeHeaderViewPaddingTop, 0, 0); + mWholeHeaderView.addView(mRefreshHeaderView, 0); + } + } + + /** + * 璁剧疆涓嬫媺鍒锋柊鎺т欢涓嬫柟鐨勮嚜瀹氫箟鎺т欢 + * + * @param customHeaderView 涓嬫媺鍒锋柊鎺т欢涓嬫柟鐨勮嚜瀹氫箟鎺т欢 + * @param scrollable 鏄惁鍙互婊氬姩 + */ + public void setCustomHeaderView(View customHeaderView, boolean scrollable) { + if (mCustomHeaderView != null && mCustomHeaderView.getParent() != null) { + ViewGroup parent = (ViewGroup) mCustomHeaderView.getParent(); + parent.removeView(mCustomHeaderView); + } + mCustomHeaderView = customHeaderView; + if (mCustomHeaderView != null) { + mCustomHeaderView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + mWholeHeaderView.addView(mCustomHeaderView); + mIsCustomHeaderViewScrollable = scrollable; + } + } + + /** + * 鍒濆鍖栦笂鎷夊姞杞芥洿澶氭帶浠� + * + * @return + */ + private void initLoadMoreFooterView() { + mLoadMoreFooterView = mRefreshViewHolder.getLoadMoreFooterView(); + if (mLoadMoreFooterView != null) { + // 娴嬮噺涓婃媺鍔犺浇鏇村鎺т欢鐨勯珮搴� + mLoadMoreFooterView.measure(0, 0); + mLoadMoreFooterViewHeight = mLoadMoreFooterView.getMeasuredHeight(); + mLoadMoreFooterView.setVisibility(GONE); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + // 琚坊鍔犲埌绐楀彛鍚庡啀璁剧疆鐩戝惉鍣紝杩欐牱寮�鍙戣�呭氨涓嶅繀鐑︽伡鍏堝垵濮嬪寲RefreshLayout杩樻槸鍏堣缃嚜瀹氫箟婊氬姩鐩戝惉鍣� + if (!mIsInitedContentViewScrollListener && mLoadMoreFooterView != null) { + setRecyclerViewOnScrollListener(); + setAbsListViewOnScrollListener(); + + addView(mLoadMoreFooterView, getChildCount()); + + mIsInitedContentViewScrollListener = true; + } + } + + private void setRecyclerViewOnScrollListener() { + if (mRecyclerView != null) { + mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if ((newState == RecyclerView.SCROLL_STATE_IDLE || newState == RecyclerView.SCROLL_STATE_SETTLING) && shouldHandleRecyclerViewLoadingMore(mRecyclerView)) { + beginLoadingMore(); + } + } + }); + } + } + + private void setAbsListViewOnScrollListener() { + if (mAbsListView != null) { + try { + // 閫氳繃鍙嶅皠鑾峰彇寮�鍙戣�呰嚜瀹氫箟鐨勬粴鍔ㄧ洃鍚櫒锛屽苟灏嗗叾鏇挎崲鎴愯嚜宸辩殑婊氬姩鐩戝惉鍣紝瑙﹀彂婊氬姩鏃朵篃瑕侀�氱煡寮�鍙戣�呰嚜瀹氫箟鐨勬粴鍔ㄧ洃鍚櫒锛堥潪渚靛叆寮忥紝涓嶈寮�鍙戣�呯户鎵跨壒瀹氱殑鎺т欢锛� + // mAbsListView.getClass().getDeclaredField("mOnScrollListener")鑾峰彇涓嶅埌mOnScrollListener锛屽繀椤婚�氳繃AbsListView.class.getDeclaredField("mOnScrollListener")鑾峰彇 + Field field = AbsListView.class.getDeclaredField("mOnScrollListener"); + field.setAccessible(true); + // 寮�鍙戣�呰嚜瀹氫箟鐨勬粴鍔ㄧ洃鍚櫒 + final AbsListView.OnScrollListener onScrollListener = (AbsListView.OnScrollListener) field.get(mAbsListView); + mAbsListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int scrollState) { + if ((scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_FLING) && shouldHandleAbsListViewLoadingMore(mAbsListView)) { + beginLoadingMore(); + } + + if (onScrollListener != null) { + onScrollListener.onScrollStateChanged(absListView, scrollState); + } + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + if (onScrollListener != null) { + onScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public boolean shouldHandleAbsListViewLoadingMore(AbsListView absListView) { + if (mIsLoadingMore || mCurrentRefreshStatus == RefreshStatus.REFRESHING || mLoadMoreFooterView == null || mDelegate == null || absListView == null || absListView.getAdapter() == null || absListView.getAdapter().getCount() == 0) { + return false; + } + + return BGARefreshScrollingUtil.isAbsListViewToBottom(absListView); + } + + public boolean shouldHandleRecyclerViewLoadingMore(RecyclerView recyclerView) { + if (mIsLoadingMore || mCurrentRefreshStatus == RefreshStatus.REFRESHING || mLoadMoreFooterView == null || mDelegate == null || recyclerView.getAdapter() == null || recyclerView.getAdapter().getItemCount() == 0) { + return false; + } + return BGARefreshScrollingUtil.isRecyclerViewToBottom(recyclerView); + } + + /** + * 鏄惁婊¤冻澶勭悊鍒锋柊鐨勬潯浠� + * + * @return + */ + private boolean shouldHandleLoadingMore() { + if (mIsLoadingMore || mCurrentRefreshStatus == RefreshStatus.REFRESHING || mLoadMoreFooterView == null || mDelegate == null) { + return false; + } + + // 鍐呭鏄櫘閫氭帶浠讹紝婊¤冻 + if (mNormalView != null) { + return true; + } + + if (BGARefreshScrollingUtil.isWebViewToBottom(mWebView)) { + return true; + } + + if (BGARefreshScrollingUtil.isScrollViewToBottom(mScrollView)) { + return true; + } + + if (mAbsListView != null) { + return shouldHandleAbsListViewLoadingMore(mAbsListView); + } + + if (mRecyclerView != null) { + return shouldHandleRecyclerViewLoadingMore(mRecyclerView); + } + + if (mStickyNavLayout != null) { + return mStickyNavLayout.shouldHandleLoadingMore(); + } + + if (BGARefreshScrollingUtil.isNestedScrollLayoutToBottom(mNestedScrollLayout)) { + return true; + } + + return false; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + mInterceptTouchDownX = event.getRawX(); + mInterceptTouchDownY = event.getRawY(); + break; + case MotionEvent.ACTION_MOVE: + if (!mIsLoadingMore && (mCurrentRefreshStatus != RefreshStatus.REFRESHING)) { + if (mInterceptTouchDownX == -1) { + mInterceptTouchDownX = (int) event.getRawX(); + } + if (mInterceptTouchDownY == -1) { + mInterceptTouchDownY = (int) event.getRawY(); + } + + int interceptTouchMoveDistanceY = (int) (event.getRawY() - mInterceptTouchDownY); + // 鍙互娌℃湁涓婃媺鍔犺浇鏇村锛屼絾鏄繀椤绘湁涓嬫媺鍒锋柊锛屽惁鍒欏氨涓嶆嫤鎴簨浠� + if (Math.abs(event.getRawX() - mInterceptTouchDownX) < Math.abs(interceptTouchMoveDistanceY) && mRefreshHeaderView != null) { + if ((interceptTouchMoveDistanceY > mTouchSlop && shouldHandleRefresh()) || (interceptTouchMoveDistanceY < -mTouchSlop && shouldHandleLoadingMore()) || (interceptTouchMoveDistanceY < -mTouchSlop && !isWholeHeaderViewCompleteInvisible()) || (interceptTouchMoveDistanceY > mTouchSlop && shouldInterceptToMoveCustomHeaderViewDown())) { + + // ACTION_DOWN鏃舵病鏈夋秷鑰楁帀浜嬩欢锛屽瓙鎺т欢浼氬浜庢寜涓嬬姸鎬侊紝杩欓噷璁剧疆ACTION_CANCEL锛屼娇瀛愭帶浠跺彇娑堟寜涓嬬姸鎬� + event.setAction(MotionEvent.ACTION_CANCEL); + super.onInterceptTouchEvent(event); + return true; + } + } + } + break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + // 閲嶇疆 + mInterceptTouchDownX = -1; + mInterceptTouchDownY = -1; + break; + } + + return super.onInterceptTouchEvent(event); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (mIsCustomHeaderViewScrollable && !isWholeHeaderViewCompleteInvisible()) { + super.dispatchTouchEvent(ev); + return true; + } + return super.dispatchTouchEvent(ev); + } + + /** + * 鏄惁婊¤冻澶勭悊鍒锋柊鐨勬潯浠� + * + * @return + */ + private boolean shouldHandleRefresh() { + if (!mPullDownRefreshEnable || mIsLoadingMore || mCurrentRefreshStatus == RefreshStatus.REFRESHING || mRefreshHeaderView == null || mDelegate == null) { + return false; + } + + return isContentViewToTop(); + } + + private boolean isContentViewToTop() { + // 鍐呭鏄櫘閫氭帶浠讹紝婊¤冻 + if (mNormalView != null) { + return true; + } + + if (BGARefreshScrollingUtil.isScrollViewOrWebViewToTop(mWebView)) { + return true; + } + + if (BGARefreshScrollingUtil.isScrollViewOrWebViewToTop(mScrollView)) { + return true; + } + + if (BGARefreshScrollingUtil.isAbsListViewToTop(mAbsListView)) { + return true; + } + + if (BGARefreshScrollingUtil.isRecyclerViewToTop(mRecyclerView)) { + return true; + } + + if (BGARefreshScrollingUtil.isStickyNavLayoutToTop(mStickyNavLayout)) { + return true; + } + + if (BGARefreshScrollingUtil.isScrollViewOrWebViewToTop(mNestedScrollLayout)) { + return true; + } + + return false; + } + + private boolean shouldInterceptToMoveCustomHeaderViewDown() { + return isContentViewToTop() && mCustomHeaderView != null && mIsCustomHeaderViewScrollable && !isCustomHeaderViewCompleteVisible(); + } + + private boolean shouldInterceptToMoveCustomHeaderViewUp() { + return isContentViewToTop() && mCustomHeaderView != null && mIsCustomHeaderViewScrollable && !isWholeHeaderViewCompleteInvisible(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (null != mRefreshHeaderView) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + mWholeHeaderDownY = (int) event.getY(); + if (mCustomHeaderView != null) { + mWholeHeaderViewDownPaddingTop = mWholeHeaderView.getPaddingTop(); + } + + if (mCustomHeaderView == null || !mIsCustomHeaderViewScrollable) { + mRefreshDownY = (int) event.getY(); + } + if (isWholeHeaderViewCompleteInvisible()) { + mRefreshDownY = (int) event.getY(); + return true; + } + break; + case MotionEvent.ACTION_MOVE: + if (handleActionMove(event)) { + return true; + } + break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + if (handleActionUpOrCancel(event)) { + return true; + } + break; + default: + break; + } + } + return super.onTouchEvent(event); + } + + /** + * 鑷畾涔夊ご閮ㄦ帶浠舵槸鍚﹀凡缁忓畬鍏ㄦ樉绀� + * + * @return true琛ㄧず宸茬粡瀹屽叏鏄剧ず锛宖alse琛ㄧず娌℃湁瀹屽叏鏄剧ず + */ + private boolean isCustomHeaderViewCompleteVisible() { + if (mCustomHeaderView != null) { + // 0琛ㄧずx锛�1琛ㄧずy + int[] location = new int[2]; + getLocationOnScreen(location); + int mOnScreenY = location[1]; + + mCustomHeaderView.getLocationOnScreen(location); + int customHeaderViewOnScreenY = location[1]; + if (mOnScreenY <= customHeaderViewOnScreenY) { + return true; + } else { + return false; + } + + } + return true; + } + + /** + * 鏁翠釜澶撮儴鎺т欢鏄惁宸茬粡瀹屽叏闅愯棌 + * + * @return true琛ㄧず瀹屽叏闅愯棌锛宖alse琛ㄧず娌℃湁瀹屽叏闅愯棌 + */ + private boolean isWholeHeaderViewCompleteInvisible() { + if (mCustomHeaderView != null && mIsCustomHeaderViewScrollable) { + // 0琛ㄧずx锛�1琛ㄧずy + int[] location = new int[2]; + getLocationOnScreen(location); + int mOnScreenY = location[1]; + + mWholeHeaderView.getLocationOnScreen(location); + int wholeHeaderViewOnScreenY = location[1]; + if (wholeHeaderViewOnScreenY + mWholeHeaderView.getMeasuredHeight() <= mOnScreenY) { + return true; + } else { + return false; + } + } + return true; + } + + /** + * 澶勭悊鎵嬫寚婊戝姩浜嬩欢 + * + * @param event + * @return true琛ㄧず鑷繁娑堣�楁帀璇ヤ簨浠讹紝false琛ㄧず涓嶆秷鑰楄浜嬩欢 + */ + private boolean handleActionMove(MotionEvent event) { + if (mCurrentRefreshStatus == RefreshStatus.REFRESHING || mIsLoadingMore) { + return false; + } + + if ((mCustomHeaderView == null || !mIsCustomHeaderViewScrollable) && mRefreshDownY == -1) { + mRefreshDownY = (int) event.getY(); + } + if (mCustomHeaderView != null && mIsCustomHeaderViewScrollable && isCustomHeaderViewCompleteVisible() && mRefreshDownY == -1) { + mRefreshDownY = (int) event.getY(); + } + + int refreshDiffY = (int) event.getY() - mRefreshDownY; + refreshDiffY = (int) (refreshDiffY / mRefreshViewHolder.getPaddingTopScale()); + + // 濡傛灉鏄悜涓嬫媺锛屽苟涓斿綋鍓嶅彲瑙佺殑绗竴涓潯鐩殑绱㈠紩绛変簬0锛屾墠澶勭悊鏁翠釜澶撮儴鎺т欢鐨刾adding + if (refreshDiffY > 0 && shouldHandleRefresh() && isCustomHeaderViewCompleteVisible()) { + int paddingTop = mMinWholeHeaderViewPaddingTop + refreshDiffY; + if (paddingTop > 0 && mCurrentRefreshStatus != RefreshStatus.RELEASE_REFRESH) { + // 涓嬫媺鍒锋柊鎺т欢瀹屽叏鏄剧ず锛屽苟涓斿綋鍓嶇姸鎬佹病鏈夊浜庨噴鏀惧紑濮嬪埛鏂扮姸鎬� + mCurrentRefreshStatus = RefreshStatus.RELEASE_REFRESH; + handleRefreshStatusChanged(); + + mRefreshViewHolder.handleScale(1.0f, refreshDiffY); + + if (mRefreshScaleDelegate != null) { + mRefreshScaleDelegate.onRefreshScaleChanged(1.0f, refreshDiffY); + } + } else if (paddingTop < 0) { + // 涓嬫媺鍒锋柊鎺т欢娌℃湁瀹屽叏鏄剧ず锛屽苟涓斿綋鍓嶇姸鎬佹病鏈夊浜庝笅鎷夊埛鏂扮姸鎬� + if (mCurrentRefreshStatus != RefreshStatus.PULL_DOWN) { + boolean isPreRefreshStatusNotIdle = mCurrentRefreshStatus != RefreshStatus.IDLE; + mCurrentRefreshStatus = RefreshStatus.PULL_DOWN; + if (isPreRefreshStatusNotIdle) { + handleRefreshStatusChanged(); + } + } + float scale = 1 - paddingTop * 1.0f / mMinWholeHeaderViewPaddingTop; + /** + * 寰�涓嬫粦 + * paddingTop mMinWholeHeaderViewPaddingTop 鍒� 0 + * scale 0 鍒� 1 + * 寰�涓婃粦 + * paddingTop 0 鍒� mMinWholeHeaderViewPaddingTop + * scale 1 鍒� 0 + */ + mRefreshViewHolder.handleScale(scale, refreshDiffY); + + if (mRefreshScaleDelegate != null) { + mRefreshScaleDelegate.onRefreshScaleChanged(scale, refreshDiffY); + } + } + paddingTop = Math.min(paddingTop, mMaxWholeHeaderViewPaddingTop); + mWholeHeaderView.setPadding(0, paddingTop, 0, 0); + + if (mRefreshViewHolder.canChangeToRefreshingStatus()) { + mWholeHeaderDownY = -1; + mRefreshDownY = -1; + + beginRefreshing(); + } + + return true; + } + + + if (mCustomHeaderView != null && mIsCustomHeaderViewScrollable) { + if (mWholeHeaderDownY == -1) { + mWholeHeaderDownY = (int) event.getY(); + + if (mCustomHeaderView != null) { + mWholeHeaderViewDownPaddingTop = mWholeHeaderView.getPaddingTop(); + } + } + + int wholeHeaderDiffY = (int) event.getY() - mWholeHeaderDownY; + if ((mPullDownRefreshEnable && !isWholeHeaderViewCompleteInvisible()) || (wholeHeaderDiffY > 0 && shouldInterceptToMoveCustomHeaderViewDown()) || (wholeHeaderDiffY < 0 && shouldInterceptToMoveCustomHeaderViewUp())) { + + int paddingTop = mWholeHeaderViewDownPaddingTop + wholeHeaderDiffY; + if (paddingTop < mMinWholeHeaderViewPaddingTop - mCustomHeaderView.getMeasuredHeight()) { + paddingTop = mMinWholeHeaderViewPaddingTop - mCustomHeaderView.getMeasuredHeight(); + } + mWholeHeaderView.setPadding(0, paddingTop, 0, 0); + + return true; + } + } + + return false; + } + + /** + * 澶勭悊鎵嬫寚鎶捣浜嬩欢 + * + * @return true琛ㄧず鑷繁娑堣�楁帀璇ヤ簨浠讹紝false琛ㄧず涓嶆秷鑰楄浜嬩欢 + */ + private boolean handleActionUpOrCancel(MotionEvent event) { + boolean isReturnTrue = false; + // 濡傛灉褰撳墠澶撮儴鍒锋柊鎺т欢娌℃湁瀹屽叏闅愯棌锛屽垯闇�瑕佽繑鍥瀟rue锛岃嚜宸辨秷鑰桝CTION_UP浜嬩欢 + if ((mCustomHeaderView == null || (mCustomHeaderView != null && !mIsCustomHeaderViewScrollable)) && mWholeHeaderView.getPaddingTop() != mMinWholeHeaderViewPaddingTop) { + isReturnTrue = true; + } + + if (mCurrentRefreshStatus == RefreshStatus.PULL_DOWN || mCurrentRefreshStatus == RefreshStatus.IDLE) { + // 澶勪簬涓嬫媺鍒锋柊鐘舵�侊紝鏉炬墜鏃堕殣钘忎笅鎷夊埛鏂版帶浠� + if (mCustomHeaderView == null || (mCustomHeaderView != null && mWholeHeaderView.getPaddingTop() < 0 && mWholeHeaderView.getPaddingTop() > mMinWholeHeaderViewPaddingTop)) { + hiddenRefreshHeaderView(); + } + mCurrentRefreshStatus = RefreshStatus.IDLE; + handleRefreshStatusChanged(); + } else if (mCurrentRefreshStatus == RefreshStatus.RELEASE_REFRESH) { + // 澶勪簬鏉惧紑杩涘叆鍒锋柊鐘舵�侊紝鏉炬墜鏃跺畬鍏ㄦ樉绀轰笅鎷夊埛鏂版帶浠讹紝杩涘叆姝e湪鍒锋柊鐘舵�� + beginRefreshing(); + } + + if (mRefreshDownY == -1) { + mRefreshDownY = (int) event.getY(); + } + int diffY = (int) event.getY() - mRefreshDownY; + if (shouldHandleLoadingMore() && diffY <= 0) { + // 澶勭悊涓婃媺鍔犺浇鏇村锛岄渶瑕佽繑鍥瀟rue锛岃嚜宸辨秷鑰桝CTION_UP浜嬩欢 + isReturnTrue = true; + beginLoadingMore(); + } + + mWholeHeaderDownY = -1; + mRefreshDownY = -1; + return isReturnTrue; + } + + /** + * 澶勭悊涓嬫媺鍒锋柊鎺т欢鐘舵�佸彉鍖� + */ + private void handleRefreshStatusChanged() { + switch (mCurrentRefreshStatus) { + case IDLE: + mRefreshViewHolder.changeToIdle(); + break; + case PULL_DOWN: + mRefreshViewHolder.changeToPullDown(); + break; + case RELEASE_REFRESH: + mRefreshViewHolder.changeToReleaseRefresh(); + break; + case REFRESHING: + mRefreshViewHolder.changeToRefreshing(); + break; + default: + break; + } + } + + /** + * 鍒囨崲鍒版鍦ㄥ埛鏂扮姸鎬侊紝浼氳皟鐢╠elegate鐨刼nBGARefreshLayoutBeginRefreshing鏂规硶 + */ + public void beginRefreshing() { + if (mCurrentRefreshStatus != RefreshStatus.REFRESHING && mDelegate != null) { + mCurrentRefreshStatus = RefreshStatus.REFRESHING; + changeRefreshHeaderViewToZero(); + handleRefreshStatusChanged(); + mDelegate.onBGARefreshLayoutBeginRefreshing(this); + } + } + + /** + * 缁撴潫涓嬫媺鍒锋柊 + */ + public void endRefreshing() { + if (mCurrentRefreshStatus == RefreshStatus.REFRESHING) { + mCurrentRefreshStatus = RefreshStatus.IDLE; + hiddenRefreshHeaderView(); + handleRefreshStatusChanged(); + mRefreshViewHolder.onEndRefreshing(); + } + } + + /** + * 闅愯棌涓嬫媺鍒锋柊鎺т欢锛屽甫鍔ㄧ敾 + */ + private void hiddenRefreshHeaderView() { + ValueAnimator animator = ValueAnimator.ofInt(mWholeHeaderView.getPaddingTop(), mMinWholeHeaderViewPaddingTop); + animator.setDuration(mRefreshViewHolder.getTopAnimDuration()); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + int paddingTop = (int) animation.getAnimatedValue(); + mWholeHeaderView.setPadding(0, paddingTop, 0, 0); + } + }); + animator.start(); + } + + /** + * 璁剧疆涓嬫媺鍒锋柊鎺т欢鐨刾addingTop鍒�0锛屽甫鍔ㄧ敾 + */ + private void changeRefreshHeaderViewToZero() { + ValueAnimator animator = ValueAnimator.ofInt(mWholeHeaderView.getPaddingTop(), 0); + animator.setDuration(mRefreshViewHolder.getTopAnimDuration()); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + int paddingTop = (int) animation.getAnimatedValue(); + mWholeHeaderView.setPadding(0, paddingTop, 0, 0); + } + }); + animator.start(); + } + + /** + * 寮�濮嬩笂鎷夊姞杞芥洿澶氾紝浼氳Е鍙慸elegate鐨刼nBGARefreshLayoutBeginRefreshing鏂规硶 + */ + public void beginLoadingMore() { + if (!mIsLoadingMore && mLoadMoreFooterView != null && mDelegate != null && mDelegate.onBGARefreshLayoutBeginLoadingMore(this)) { + mIsLoadingMore = true; + + if (mIsShowLoadingMoreView) { + showLoadingMoreView(); + } + } + } + + /** + * 鏄剧ず涓婃媺鍔犺浇鏇村鎺т欢 + */ + private void showLoadingMoreView() { + mRefreshViewHolder.changeToLoadingMore(); + mLoadMoreFooterView.setVisibility(VISIBLE); + + BGARefreshScrollingUtil.scrollToBottom(mScrollView); + BGARefreshScrollingUtil.scrollToBottom(mRecyclerView); + BGARefreshScrollingUtil.scrollToBottom(mAbsListView); + if (mStickyNavLayout != null) { + mStickyNavLayout.scrollToBottom(); + } + } + + /** + * 缁撴潫涓婃媺鍔犺浇鏇村 + */ + public void endLoadingMore() { + if (mIsLoadingMore) { + if (mIsShowLoadingMoreView) { + // 閬垮厤WiFi鐜涓嬭姹傛暟鎹お蹇紝鍔犺浇鏇村鎺т欢涓�闂�岃繃 + mHandler.postDelayed(mDelayHiddenLoadingMoreViewTask, 300); + } else { + mIsLoadingMore = false; + } + } + } + + private Runnable mDelayHiddenLoadingMoreViewTask = new Runnable() { + @Override + public void run() { + mIsLoadingMore = false; + mRefreshViewHolder.onEndLoadingMore(); + mLoadMoreFooterView.setVisibility(GONE); + } + }; + + /** + * 涓婃媺鍔犺浇鏇村鏃舵槸鍚︽樉绀哄姞杞芥洿澶氭帶浠� + * + * @param isShowLoadingMoreView + */ + public void setIsShowLoadingMoreView(boolean isShowLoadingMoreView) { + mIsShowLoadingMoreView = isShowLoadingMoreView; + } + + /** + * 璁剧疆涓嬫媺鍒锋柊鏄惁鍙敤 + * + * @param pullDownRefreshEnable + */ + public void setPullDownRefreshEnable(boolean pullDownRefreshEnable) { + mPullDownRefreshEnable = pullDownRefreshEnable; + } + + /** + * 璁剧疆涓嬫媺鍒锋柊涓婃媺鍔犺浇鏇村浠g悊 + * + * @param delegate + */ + public void setDelegate(BGARefreshLayoutDelegate delegate) { + mDelegate = delegate; + } + + /** + * 璁剧疆涓嬫媺鍒锋柊鎺т欢鍙鏃讹紝涓婁笅鎷夎繘搴︾殑浠g悊 + * + * @param refreshScaleDelegate + */ + public void setRefreshScaleDelegate(BGARefreshScaleDelegate refreshScaleDelegate) { + mRefreshScaleDelegate = refreshScaleDelegate; + } + + /** + * 鑾峰彇褰撳墠涓嬫媺鍒锋柊鐨勭姸鎬� + * + * @return + */ + public RefreshStatus getCurrentRefreshStatus() { + return mCurrentRefreshStatus; + } + + /** + * 鏄惁澶勪簬姝e湪鍔犺浇鏇村鐘舵�� + * + * @return + */ + public boolean isLoadingMore() { + return mIsLoadingMore; + } + + public interface BGARefreshLayoutDelegate { + /** + * 寮�濮嬪埛鏂� + */ + void onBGARefreshLayoutBeginRefreshing(BGARefreshLayout refreshLayout); + + /** + * 寮�濮嬪姞杞芥洿澶氥�傜敱浜庣洃鍚簡ScrollView銆丷ecyclerView銆丄bsListView婊氬姩鍒板簳閮ㄧ殑浜嬩欢锛屾墍浠ヨ繖閲岄噰鐢ㄨ繑鍥瀊oolean鏉ュ鐞嗘槸鍚﹀姞杞芥洿澶氥�傚惁鍒欎娇鐢╡ndLoadingMore鏂规硶浼氬け鏁� + * + * @param refreshLayout + * @return 濡傛灉瑕佸紑濮嬪姞杞芥洿澶氬垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse銆傦紙杩斿洖false鐨勫満鏅細娌℃湁缃戠粶銆佷竴鍏卞彧鏈墄椤垫暟鎹苟涓斿凡缁忓姞杞戒簡x椤垫暟鎹簡锛� + */ + boolean onBGARefreshLayoutBeginLoadingMore(BGARefreshLayout refreshLayout); + } + + public interface BGARefreshScaleDelegate { + /** + * 涓嬫媺鍒锋柊鎺т欢鍙鏃讹紝澶勭悊涓婁笅鎷夎繘搴� + * + * @param scale 涓嬫媺杩囩▼0 鍒� 1锛屽洖寮硅繃绋�1 鍒� 0锛屾病鏈夊姞涓婂脊绨ц窛绂荤Щ鍔ㄦ椂鐨勬瘮渚� + * @param moveYDistance 鏁翠釜涓嬫媺鍒锋柊鎺т欢paddingTop鍙樺寲鐨勫�硷紝濡傛灉鏈夊脊绨ц窛绂伙紝浼氬ぇ浜庢暣涓笅鎷夊埛鏂版帶浠剁殑楂樺害 + */ + void onRefreshScaleChanged(float scale, int moveYDistance); + } + + public enum RefreshStatus { + IDLE, PULL_DOWN, RELEASE_REFRESH, REFRESHING + } + + public static int dp2px(Context context, int dpValue) { + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.getResources().getDisplayMetrics()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshScrollingUtil.java b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshScrollingUtil.java new file mode 100644 index 0000000..29b4a7f --- /dev/null +++ b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshScrollingUtil.java @@ -0,0 +1,292 @@ +/** + * Copyright 2015 bingoogolapple + * <p/> + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hdl.photovoltaic.widget.refreshlayout; + +import android.content.Context; +import android.graphics.Rect; +import android.util.DisplayMetrics; +import android.view.View; +import android.view.ViewParent; +import android.view.WindowManager; +import android.webkit.WebView; +import android.widget.AbsListView; +import android.widget.ScrollView; + +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + + +import java.lang.reflect.Field; + +/** + * 浣滆��:鐜嬫旦 閭欢:bingoogolapple@gmail.com + * 鍒涘缓鏃堕棿:15/10/28 涓婂崍2:26 + * 鎻忚堪: + */ +public class BGARefreshScrollingUtil { + + private BGARefreshScrollingUtil() { + } + + public static boolean isScrollViewOrWebViewToTop(View view) { + return view != null && view.getScrollY() == 0; + } + + public static boolean isAbsListViewToTop(AbsListView absListView) { + if (absListView != null) { + int firstChildTop = 0; + if (absListView.getChildCount() > 0) { + // 濡傛灉AdapterView鐨勫瓙鎺т欢鏁伴噺涓嶄负0锛岃幏鍙栫涓�涓瓙鎺т欢鐨則op + firstChildTop = absListView.getChildAt(0).getTop() - absListView.getPaddingTop(); + } + if (absListView.getFirstVisiblePosition() == 0 && firstChildTop == 0) { + return true; + } + } + return false; + } + + public static boolean isRecyclerViewToTop(RecyclerView recyclerView) { + if (recyclerView != null) { + RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); + if (manager == null) { + return true; + } + if (manager.getItemCount() == 0) { + return true; + } + + if (manager instanceof LinearLayoutManager) { + LinearLayoutManager layoutManager = (LinearLayoutManager) manager; + + int firstChildTop = 0; + if (recyclerView.getChildCount() > 0) { + // 澶勭悊item楂樺害瓒呰繃涓�灞忓箷鏃剁殑鎯呭喌 + View firstVisibleChild = recyclerView.getChildAt(0); + if (firstVisibleChild != null && firstVisibleChild.getMeasuredHeight() >= recyclerView.getMeasuredHeight()) { + if (android.os.Build.VERSION.SDK_INT < 14) { + return !(ViewCompat.canScrollVertically(recyclerView, -1) || recyclerView.getScrollY() > 0); + } else { + return !ViewCompat.canScrollVertically(recyclerView, -1); + } + } + + // 濡傛灉RecyclerView鐨勫瓙鎺т欢鏁伴噺涓嶄负0锛岃幏鍙栫涓�涓瓙鎺т欢鐨則op + // 瑙e喅item鐨則opMargin涓嶄负0鏃朵笉鑳借Е鍙戜笅鎷夊埛鏂� + View firstChild = recyclerView.getChildAt(0); + RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) firstChild.getLayoutParams(); + firstChildTop = firstChild.getTop() - layoutParams.topMargin - getRecyclerViewItemTopInset(layoutParams) - recyclerView.getPaddingTop(); + } + + if (layoutManager.findFirstCompletelyVisibleItemPosition() < 1 && firstChildTop == 0) { + return true; + } + } else if (manager instanceof StaggeredGridLayoutManager) { + StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) manager; + + int[] out = layoutManager.findFirstCompletelyVisibleItemPositions(null); + if (out[0] < 1) { + return true; + } + } + } + return false; + } + + /** + * 閫氳繃鍙嶅皠鑾峰彇RecyclerView鐨刬tem鐨則opInset + * + * @param layoutParams + * @return + */ + private static int getRecyclerViewItemTopInset(RecyclerView.LayoutParams layoutParams) { + try { + Field field = RecyclerView.LayoutParams.class.getDeclaredField("mDecorInsets"); + field.setAccessible(true); + // 寮�鍙戣�呰嚜瀹氫箟鐨勬粴鍔ㄧ洃鍚櫒 + Rect decorInsets = (Rect) field.get(layoutParams); + return decorInsets.top; + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + public static boolean isStickyNavLayoutToTop(BGAStickyNavLayout stickyNavLayout) { + return isScrollViewOrWebViewToTop(stickyNavLayout) && stickyNavLayout.isContentViewToTop(); + } + + + public static boolean isWebViewToBottom(WebView webView) { + return webView != null && webView.getContentHeight() * webView.getScale() == (webView.getScrollY() + webView.getMeasuredHeight()); + } + + public static boolean isScrollViewToBottom(ScrollView scrollView) { + if (scrollView != null) { + int scrollContentHeight = scrollView.getScrollY() + scrollView.getMeasuredHeight() - scrollView.getPaddingTop() - scrollView.getPaddingBottom(); + int realContentHeight = scrollView.getChildAt(0).getMeasuredHeight(); + if (scrollContentHeight == realContentHeight) { + return true; + } + } + return false; + } + + public static boolean isNestedScrollLayoutToBottom(NestedScrollLayout nestedScrollLayout) { + if (nestedScrollLayout != null) { + int scrollContentHeight = nestedScrollLayout.getScrollY() + nestedScrollLayout.getMeasuredHeight() - nestedScrollLayout.getPaddingTop() - nestedScrollLayout.getPaddingBottom(); + int realContentHeight = nestedScrollLayout.getChildAt(0).getMeasuredHeight(); + if (scrollContentHeight == realContentHeight) { + return true; + } + } + return false; + } + + public static boolean isAbsListViewToBottom(AbsListView absListView) { + if (absListView != null && absListView.getAdapter() != null && absListView.getChildCount() > 0 && absListView.getLastVisiblePosition() == absListView.getAdapter().getCount() - 1) { + View lastChild = absListView.getChildAt(absListView.getChildCount() - 1); + + BGAStickyNavLayout stickyNavLayout = getStickyNavLayout(absListView); + if (stickyNavLayout != null) { + // 澶勭悊BGAStickyNavLayout涓璴astChild.getBottom() <= absListView.getMeasuredHeight()澶辨晥闂 + + // 0琛ㄧずx锛�1琛ㄧずy + int[] location = new int[2]; + lastChild.getLocationOnScreen(location); + int lastChildBottomOnScreen = location[1] + lastChild.getMeasuredHeight(); + stickyNavLayout.getLocationOnScreen(location); + int stickyNavLayoutBottomOnScreen = location[1] + stickyNavLayout.getMeasuredHeight(); + return lastChildBottomOnScreen + absListView.getPaddingBottom() <= stickyNavLayoutBottomOnScreen; + } else { + return lastChild.getBottom() <= absListView.getMeasuredHeight(); + } + } + return false; + } + + public static boolean isRecyclerViewToBottom(RecyclerView recyclerView) { + if (recyclerView != null) { + RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); + if (manager == null || manager.getItemCount() == 0) { + return false; + } + + if (manager instanceof LinearLayoutManager) { + // 澶勭悊item楂樺害瓒呰繃涓�灞忓箷鏃剁殑鎯呭喌 + View lastVisibleChild = recyclerView.getChildAt(recyclerView.getChildCount() - 1); + if (lastVisibleChild != null && lastVisibleChild.getMeasuredHeight() >= recyclerView.getMeasuredHeight()) { + if (android.os.Build.VERSION.SDK_INT < 14) { + return !(ViewCompat.canScrollVertically(recyclerView, 1) || recyclerView.getScrollY() < 0); + } else { + return !ViewCompat.canScrollVertically(recyclerView, 1); + } + } + + LinearLayoutManager layoutManager = (LinearLayoutManager) manager; + if (layoutManager.findLastCompletelyVisibleItemPosition() == layoutManager.getItemCount() - 1) { + BGAStickyNavLayout stickyNavLayout = getStickyNavLayout(recyclerView); + if (stickyNavLayout != null) { + // 澶勭悊BGAStickyNavLayout涓璮indLastCompletelyVisibleItemPosition澶辨晥闂 + View lastCompletelyVisibleChild = layoutManager.getChildAt(layoutManager.findLastCompletelyVisibleItemPosition()); + if (lastCompletelyVisibleChild == null) { + return true; + } else { + // 0琛ㄧずx锛�1琛ㄧずy + int[] location = new int[2]; + lastCompletelyVisibleChild.getLocationOnScreen(location); + int lastChildBottomOnScreen = location[1] + lastCompletelyVisibleChild.getMeasuredHeight(); + stickyNavLayout.getLocationOnScreen(location); + int stickyNavLayoutBottomOnScreen = location[1] + stickyNavLayout.getMeasuredHeight(); + return lastChildBottomOnScreen <= stickyNavLayoutBottomOnScreen; + } + } else { + return true; + } + } + } else if (manager instanceof StaggeredGridLayoutManager) { + StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) manager; + + int[] out = layoutManager.findLastCompletelyVisibleItemPositions(null); + int lastPosition = layoutManager.getItemCount() - 1; + for (int position : out) { + if (position == lastPosition) { + return true; + } + } + } + } + return false; + } + + + public static void scrollToBottom(final ScrollView scrollView) { + if (scrollView != null) { + scrollView.post(new Runnable() { + @Override + public void run() { + scrollView.fullScroll(ScrollView.FOCUS_DOWN); + } + }); + } + } + + public static void scrollToBottom(final AbsListView absListView) { + if (absListView != null) { + if (absListView.getAdapter() != null && absListView.getAdapter().getCount() > 0) { + absListView.post(new Runnable() { + @Override + public void run() { + absListView.setSelection(absListView.getAdapter().getCount() - 1); + } + }); + } + } + } + + public static void scrollToBottom(final RecyclerView recyclerView) { + if (recyclerView != null) { + if (recyclerView.getAdapter() != null && recyclerView.getAdapter().getItemCount() > 0) { + recyclerView.post(new Runnable() { + @Override + public void run() { + recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount() - 1); + } + }); + } + } + } + + public static BGAStickyNavLayout getStickyNavLayout(View view) { + ViewParent viewParent = view.getParent(); + while (viewParent != null) { + if (viewParent instanceof BGAStickyNavLayout) { + return (BGAStickyNavLayout) viewParent; + } + viewParent = viewParent.getParent(); + } + return null; + } + + public static int getScreenHeight(Context context) { + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics dm = new DisplayMetrics(); + windowManager.getDefaultDisplay().getMetrics(dm); + return dm.heightPixels; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshViewHolder.java b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshViewHolder.java new file mode 100644 index 0000000..add62be --- /dev/null +++ b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGARefreshViewHolder.java @@ -0,0 +1,345 @@ +/** + * Copyright 2015 bingoogolapple + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hdl.photovoltaic.widget.refreshlayout; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.AnimationDrawable; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; + +import com.hdl.photovoltaic.R; + + +/** + * 浣滆��:鐜嬫旦 閭欢:bingoogolapple@gmail.com + * 鍒涘缓鏃堕棿:15/5/21 12:56 + * 鎻忚堪:缁ф壙璇ユ娊璞$被瀹炵幇鍝嶅簲鐨勬娊璞℃柟娉曪紝鍋氬嚭鍚勭涓嬫媺鍒锋柊鏁堟灉銆傚弬鑰傿GANormalRefreshViewHolder銆丅GAStickinessRefreshViewHolder銆丅GAMoocStyleRefreshViewHolder銆丅GAMeiTuanRefreshViewHolder + */ +public abstract class BGARefreshViewHolder { + /** + * 鎵嬫寚绉诲姩璺濈涓庝笅鎷夊埛鏂版帶浠秔addingTop绉诲姩璺濈鐨勬瘮鍊� + */ + private static final float PULL_DISTANCE_SCALE = 1.8f; + /** + * 鎵嬫寚绉诲姩璺濈涓庝笅鎷夊埛鏂版帶浠秔addingTop绉诲姩璺濈鐨勬瘮鍊硷紝榛樿1.8f + */ + private float mPullDistanceScale = PULL_DISTANCE_SCALE; + /** + * 涓嬫媺鍒锋柊鎺т欢paddingTop鐨勫脊绨ц窛绂讳笌涓嬫媺鍒锋柊鎺т欢楂樺害鐨勬瘮鍊� + */ + private static final float SPRING_DISTANCE_SCALE = 0.4f; + /** + * 涓嬫媺鍒锋柊鎺т欢paddingTop鐨勫脊绨ц窛绂讳笌涓嬫媺鍒锋柊鎺т欢楂樺害鐨勬瘮鍊硷紝榛樿0.4f + */ + private float mSpringDistanceScale = SPRING_DISTANCE_SCALE; + + protected Context mContext; + /** + * 涓嬫媺鍒锋柊涓婃媺鍔犺浇鏇村鎺т欢 + */ + protected BGARefreshLayout mRefreshLayout; + /** + * 涓嬫媺鍒锋柊鎺т欢 + */ + protected View mRefreshHeaderView; + /** + * 涓婃媺鍔犺浇鏇村鎺т欢 + */ + protected View mLoadMoreFooterView; + /** + * 搴曢儴鍔犺浇鏇村鎻愮ず鎺т欢 + */ + protected TextView mFooterStatusTv; + /** + * 搴曢儴鍔犺浇鏇村鑿婅姳鎺т欢 + */ + protected ImageView mFooterChrysanthemumIv; + /** + * 搴曢儴鍔犺浇鏇村鑿婅姳drawable + */ + protected AnimationDrawable mFooterChrysanthemumAd; + /** + * 姝e湪鍔犺浇鏇村鏃剁殑鏂囨湰 + */ + protected String mLodingMoreText = "鍔犺浇涓�..."; + /** + * 鏄惁寮�鍚姞杞芥洿澶氬姛鑳� + */ + private boolean mIsLoadingMoreEnabled = true; + /** + * 鏁翠釜鍔犺浇鏇村鎺т欢鐨勮儗鏅鑹茶祫婧恑d + */ + private int mLoadMoreBackgroundColorRes = -1; + /** + * 鏁翠釜鍔犺浇鏇村鎺т欢鐨勮儗鏅痙rawable璧勬簮id + */ + private int mLoadMoreBackgroundDrawableRes = -1; + /** + * 涓嬫媺鍒锋柊鎺т欢鐨勮儗鏅鑹茶祫婧恑d + */ + protected int mRefreshViewBackgroundColorRes = -1; + /** + * 涓嬫媺鍒锋柊鎺т欢鐨勮儗鏅痙rawable璧勬簮id + */ + protected int mRefreshViewBackgroundDrawableRes = -1; + /** + * 澶撮儴鎺т欢绉诲姩鍔ㄧ敾鏃跺父 + */ + private int mTopAnimDuration = 500; + + /** + * @param context + * @param isLoadingMoreEnabled 涓婃媺鍔犺浇鏇村鏄惁鍙敤 + */ + public BGARefreshViewHolder(Context context, boolean isLoadingMoreEnabled) { + mContext = context; + mIsLoadingMoreEnabled = isLoadingMoreEnabled; + } + + /** + * 璁剧疆姝e湪鍔犺浇鏇村鏃剁殑鏂囨湰 + * + * @param loadingMoreText + */ + public void setLoadingMoreText(String loadingMoreText) { + mLodingMoreText = loadingMoreText; + } + + /** + * 璁剧疆鏁翠釜鍔犺浇鏇村鎺т欢鐨勮儗鏅鑹茶祫婧恑d + * + * @param loadMoreBackgroundColorRes + */ + public void setLoadMoreBackgroundColorRes(@ColorRes int loadMoreBackgroundColorRes) { + mLoadMoreBackgroundColorRes = loadMoreBackgroundColorRes; + } + + /** + * 璁剧疆鏁翠釜鍔犺浇鏇村鎺т欢鐨勮儗鏅痙rawable璧勬簮id + * + * @param loadMoreBackgroundDrawableRes + */ + public void setLoadMoreBackgroundDrawableRes(@DrawableRes int loadMoreBackgroundDrawableRes) { + mLoadMoreBackgroundDrawableRes = loadMoreBackgroundDrawableRes; + } + + /** + * 璁剧疆涓嬫媺鍒锋柊鎺т欢鐨勮儗鏅鑹茶祫婧恑d + * + * @param refreshViewBackgroundColorRes + */ + public void setRefreshViewBackgroundColorRes(@ColorRes int refreshViewBackgroundColorRes) { + mRefreshViewBackgroundColorRes = refreshViewBackgroundColorRes; + } + + /** + * 璁剧疆涓嬫媺鍒锋柊鎺т欢鐨勮儗鏅痙rawable璧勬簮id + * + * @param refreshViewBackgroundDrawableRes + */ + public void setRefreshViewBackgroundDrawableRes(@DrawableRes int refreshViewBackgroundDrawableRes) { + mRefreshViewBackgroundDrawableRes = refreshViewBackgroundDrawableRes; + } + + /** + * 鑾峰彇椤堕儴鏈弧瓒充笅鎷夊埛鏂版潯浠舵椂鍥炲脊鍒板垵濮嬬姸鎬併�佹弧瓒冲埛鏂版潯浠舵椂鍥炲脊鍒版鍦ㄥ埛鏂扮姸鎬併�佸埛鏂板畬姣曞悗鍥炲脊鍒板垵濮嬬姸鎬佺殑鍔ㄧ敾鏃堕棿锛岄粯璁や负500姣 + * + * @return + */ + public int getTopAnimDuration() { + return mTopAnimDuration; + } + + /** + * 璁剧疆椤堕儴鏈弧瓒充笅鎷夊埛鏂版潯浠舵椂鍥炲脊鍒板垵濮嬬姸鎬併�佹弧瓒冲埛鏂版潯浠舵椂鍥炲脊鍒版鍦ㄥ埛鏂扮姸鎬併�佸埛鏂板畬姣曞悗鍥炲脊鍒板垵濮嬬姸鎬佺殑鍔ㄧ敾鏃堕棿锛岄粯璁や负300姣 + * + * @param topAnimDuration + */ + public void setTopAnimDuration(int topAnimDuration) { + mTopAnimDuration = topAnimDuration; + } + + /** + * 鑾峰彇涓婃媺鍔犺浇鏇村鎺т欢锛屽鏋滀笉鍠滄杩欑涓婃媺鍒锋柊椋庢牸鍙噸鍐欒鏂规硶瀹炵幇鑷畾涔塋oadMoreFooterView + * + * @return + */ + public View getLoadMoreFooterView() { + if (!mIsLoadingMoreEnabled) { + return null; + } + if (mLoadMoreFooterView == null) { + mLoadMoreFooterView = View.inflate(mContext, R.layout.loading_alert, null); + mLoadMoreFooterView.setBackgroundColor(Color.TRANSPARENT); + if (mLoadMoreBackgroundColorRes != -1) { + mLoadMoreFooterView.setBackgroundResource(mLoadMoreBackgroundColorRes); + } + if (mLoadMoreBackgroundDrawableRes != -1) { + mLoadMoreFooterView.setBackgroundResource(mLoadMoreBackgroundDrawableRes); + } + mFooterStatusTv = (TextView) mLoadMoreFooterView.findViewById(R.id.load_content_tv); + mFooterChrysanthemumIv = (ImageView) mLoadMoreFooterView.findViewById(R.id.load_pb); + mFooterChrysanthemumIv.setBackground(mContext.getDrawable(R.drawable.progress_small)); + mFooterChrysanthemumAd = (AnimationDrawable) mFooterChrysanthemumIv.getDrawable(); + mFooterStatusTv.setText(mLodingMoreText); + } + return mLoadMoreFooterView; + } + + /** + * 鑾峰彇澶撮儴涓嬫媺鍒锋柊鎺т欢 + * + * @return + */ + public abstract View getRefreshHeaderView(); + + /** + * 涓嬫媺鍒锋柊鎺т欢鍙鏃讹紝澶勭悊涓婁笅鎷夎繘搴� + * + * @param scale 涓嬫媺杩囩▼0 鍒� 1锛屽洖寮硅繃绋�1 鍒� 0锛屾病鏈夊姞涓婂脊绨ц窛绂荤Щ鍔ㄦ椂鐨勬瘮渚� + * @param moveYDistance 鏁翠釜涓嬫媺鍒锋柊鎺т欢paddingTop鍙樺寲鐨勫�硷紝濡傛灉鏈夊脊绨ц窛绂伙紝浼氬ぇ浜庢暣涓笅鎷夊埛鏂版帶浠剁殑楂樺害 + */ + public abstract void handleScale(float scale, int moveYDistance); + + /** + * 杩涘叆鍒版湭澶勭悊涓嬫媺鍒锋柊鐘舵�� + */ + public abstract void changeToIdle(); + + /** + * 杩涘叆涓嬫媺鐘舵�� + */ + public abstract void changeToPullDown(); + + /** + * 杩涘叆閲婃斁鍒锋柊鐘舵�� + */ + public abstract void changeToReleaseRefresh(); + + /** + * 杩涘叆姝e湪鍒锋柊鐘舵�� + */ + public abstract void changeToRefreshing(); + + /** + * 缁撴潫涓嬫媺鍒锋柊 + */ + public abstract void onEndRefreshing(); + + /** + * 鎵嬫寚绉诲姩璺濈涓庝笅鎷夊埛鏂版帶浠秔addingTop绉诲姩璺濈鐨勬瘮鍊� + * + * @return + */ + public float getPaddingTopScale() { + return mPullDistanceScale; + } + + /** + * 璁剧疆鎵嬫寚绉诲姩璺濈涓庝笅鎷夊埛鏂版帶浠秔addingTop绉诲姩璺濈鐨勬瘮鍊� + * + * @param pullDistanceScale + */ + public void setPullDistanceScale(float pullDistanceScale) { + mPullDistanceScale = pullDistanceScale; + } + + /** + * 涓嬫媺鍒锋柊鎺т欢paddingTop鐨勫脊绨ц窛绂讳笌涓嬫媺鍒锋柊鎺т欢楂樺害鐨勬瘮鍊� + * + * @return + */ + public float getSpringDistanceScale() { + return mSpringDistanceScale; + } + + /** + * 璁剧疆涓嬫媺鍒锋柊鎺т欢paddingTop鐨勫脊绨ц窛绂讳笌涓嬫媺鍒锋柊鎺т欢楂樺害鐨勬瘮鍊硷紝涓嶈兘灏忎簬0锛屽鏋滃埛鏂版帶浠舵瘮杈冮珮锛屽缓璁皢璇ュ�艰缃皬涓�浜� + * + * @param springDistanceScale + */ + public void setSpringDistanceScale(float springDistanceScale) { + if (springDistanceScale < 0) { + throw new RuntimeException("涓嬫媺鍒锋柊鎺т欢paddingTop鐨勫脊绨ц窛绂讳笌涓嬫媺鍒锋柊鎺т欢楂樺害鐨勬瘮鍊約pringDistanceScale涓嶈兘灏忎簬0"); + } + mSpringDistanceScale = springDistanceScale; + } + + /** + * 鏄浜庤兘澶熻繘鍏ュ埛鏂扮姸鎬� + * + * @return + */ + public boolean canChangeToRefreshingStatus() { + return false; + } + + /** + * 杩涘叆鍔犺浇鏇村鐘舵�� + */ + public void changeToLoadingMore() { + if (mIsLoadingMoreEnabled && mFooterChrysanthemumAd != null) { + mFooterChrysanthemumAd.start(); + } + } + + /** + * 缁撴潫涓婃媺鍔犺浇鏇村 + */ + public void onEndLoadingMore() { + if (mIsLoadingMoreEnabled && mFooterChrysanthemumAd != null) { + mFooterChrysanthemumAd.stop(); + } + } + + /** + * 鑾峰彇涓嬫媺鍒锋柊鎺т欢鐨勯珮搴︼紝濡傛灉鍒濆鍖栨椂鐨勯珮搴﹀拰鏈�鍚庡睍寮�鐨勬渶澶ч珮搴︿笉涓�鑷达紝闇�閲嶅啓璇ユ柟娉曡繑鍥炴渶澶ч珮搴� + * + * @return + */ + public int getRefreshHeaderViewHeight() { + if (mRefreshHeaderView != null) { + // 娴嬮噺涓嬫媺鍒锋柊鎺т欢鐨勯珮搴� + mRefreshHeaderView.measure(0, 0); + return mRefreshHeaderView.getMeasuredHeight(); + } + return 0; + } + + /** + * 鏀瑰彉鏁翠釜涓嬫媺鍒锋柊澶撮儴鎺т欢绉诲姩涓�瀹氱殑璺濈锛堝甫鍔ㄧ敾锛夛紝鑷畾涔夊埛鏂版帶浠惰繘鍏ュ埛鏂扮姸鎬佸墠鍚庣殑楂樺害鏈夊彉鍖栨椂鍙互浣跨敤璇ユ柟娉曪紙鍙傝�傿GAStickinessRefreshView锛� + * + * @param distance + */ + public void startChangeWholeHeaderViewPaddingTop(int distance) { + mRefreshLayout.startChangeWholeHeaderViewPaddingTop(distance); + } + + /** + * 璁剧疆涓嬫媺鍒锋柊涓婃媺鍔犺浇鏇村鎺т欢锛岃鏂规硶鏄缃瓸GARefreshViewHolder缁橞GARefreshLayout鏃剁敱BGARefreshLayout璋冪敤 + * + * @param refreshLayout + */ + public void setRefreshLayout(BGARefreshLayout refreshLayout) { + mRefreshLayout = refreshLayout; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGAStickyNavLayout.java b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGAStickyNavLayout.java new file mode 100644 index 0000000..e8bfcef --- /dev/null +++ b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/BGAStickyNavLayout.java @@ -0,0 +1,520 @@ +/** + * Copyright 2015 bingoogolapple + * <p/> + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hdl.photovoltaic.widget.refreshlayout; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.webkit.WebView; +import android.widget.AbsListView; +import android.widget.LinearLayout; +import android.widget.OverScroller; +import android.widget.ScrollView; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +/** + * 浣滆��:鐜嬫旦 閭欢:bingoogolapple@gmail.com + * 鍒涘缓鏃堕棿:15/10/28 涓婂崍2:32 + * 鎻忚堪: + */ +public class BGAStickyNavLayout extends LinearLayout { + private View mHeaderView; + private View mNavView; + private View mContentView; + + private View mDirectNormalView; + private RecyclerView mDirectRecyclerView; + private AbsListView mDirectAbsListView; + private ScrollView mDirectScrollView; + private WebView mDirectWebView; + private ViewPager mDirectViewPager; + + private View mNestedContentView; + private View mNestedNormalView; + private RecyclerView mNestedRecyclerView; + private AbsListView mNestedAbsListView; + private ScrollView mNestedScrollView; + private WebView mNestedWebView; + + private OverScroller mOverScroller; + private VelocityTracker mVelocityTracker; + private int mTouchSlop; + private int mMaximumVelocity; + private int mMinimumVelocity; + + private boolean mIsInControl = true; + + private float mLastDispatchY; + private float mLastTouchY; + + public BGARefreshLayout mRefreshLayout; + + public BGAStickyNavLayout(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + private void init(Context context) { + setOrientation(VERTICAL); + + mOverScroller = new OverScroller(context); + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = configuration.getScaledTouchSlop(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + } + + @Override + public void setOrientation(int orientation) { + if (VERTICAL == orientation) { + super.setOrientation(VERTICAL); + } + } + + @Override + public void onFinishInflate() { + super.onFinishInflate(); + + if (getChildCount() != 3) { + throw new IllegalStateException(BGAStickyNavLayout.class.getSimpleName() + "蹇呴』鏈変笖鍙湁涓変釜瀛愭帶浠�"); + } + + mHeaderView = getChildAt(0); + mNavView = getChildAt(1); + mContentView = getChildAt(2); + + if (mContentView instanceof AbsListView) { + mDirectAbsListView = (AbsListView) mContentView; + mDirectAbsListView.setOnScrollListener(mLvOnScrollListener); + } else if (mContentView instanceof RecyclerView) { + mDirectRecyclerView = (RecyclerView) mContentView; + mDirectRecyclerView.addOnScrollListener(mRvOnScrollListener); + } else if (mContentView instanceof ScrollView) { + mDirectScrollView = (ScrollView) mContentView; + } else if (mContentView instanceof WebView) { + mDirectWebView = (WebView) mContentView; + } else if (mContentView instanceof ViewPager) { + mDirectViewPager = (ViewPager) mContentView; + mDirectViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + regetNestedContentView(); + } + }); + } else { + mDirectNormalView = mContentView; + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + measureChild(mContentView, widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - getNavViewHeight(), MeasureSpec.EXACTLY)); + } + + @Override + public void computeScroll() { + if (mOverScroller.computeScrollOffset()) { + scrollTo(0, mOverScroller.getCurrY()); + invalidate(); + } + } + + public void fling(int velocityY) { + mOverScroller.fling(0, getScrollY(), 0, velocityY, 0, 0, 0, getHeaderViewHeight()); + invalidate(); + } + + @Override + public void scrollTo(int x, int y) { + if (y < 0) { + y = 0; + } + + int headerViewHeight = getHeaderViewHeight(); + if (y > headerViewHeight) { + y = headerViewHeight; + } + + if (y != getScrollY()) { + super.scrollTo(x, y); + } + } + + /** + * 鑾峰彇澶撮儴瑙嗗浘楂樺害锛屽寘鎷瑃opMargin鍜宐ottomMargin + * + * @return + */ + private int getHeaderViewHeight() { + MarginLayoutParams layoutParams = (MarginLayoutParams) mHeaderView.getLayoutParams(); + return mHeaderView.getMeasuredHeight() + layoutParams.topMargin + layoutParams.bottomMargin; + } + + /** + * 鑾峰彇瀵艰埅瑙嗗浘鐨勯珮搴︼紝鍖呮嫭topMargin鍜宐ottomMargin + * + * @return + */ + private int getNavViewHeight() { + MarginLayoutParams layoutParams = (MarginLayoutParams) mNavView.getLayoutParams(); + return mNavView.getMeasuredHeight() + layoutParams.topMargin + layoutParams.bottomMargin; + } + + /** + * 澶撮儴瑙嗗浘鏄惁宸茬粡瀹屽叏闅愯棌 + * + * @return + */ + private boolean isHeaderViewCompleteInvisible() { + // 0琛ㄧずx锛�1琛ㄧずy + int[] location = new int[2]; + getLocationOnScreen(location); + int contentOnScreenTopY = location[1] + getPaddingTop(); + + mNavView.getLocationOnScreen(location); + MarginLayoutParams params = (MarginLayoutParams) mNavView.getLayoutParams(); + int navViewTopOnScreenY = location[1] - params.topMargin; + + if (navViewTopOnScreenY == contentOnScreenTopY) { + return true; + } else { + return false; + } + } + + private void initVelocityTrackerIfNotExists() { + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + } + + private void recycleVelocityTracker() { + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + float currentTouchY = ev.getY(); + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + mLastDispatchY = currentTouchY; + break; + case MotionEvent.ACTION_MOVE: + float differentY = currentTouchY - mLastDispatchY; + mLastDispatchY = currentTouchY; + if (isContentViewToTop() && isHeaderViewCompleteInvisible()) { + if (differentY >= 0 && !mIsInControl) { + mIsInControl = true; + + return resetDispatchTouchEvent(ev); + } + + if (differentY <= 0 && mIsInControl) { + mIsInControl = false; + + return resetDispatchTouchEvent(ev); + } + } + break; + } + return super.dispatchTouchEvent(ev); + } + + private boolean resetDispatchTouchEvent(MotionEvent ev) { + MotionEvent newEvent = MotionEvent.obtain(ev); + + ev.setAction(MotionEvent.ACTION_CANCEL); + dispatchTouchEvent(ev); + + newEvent.setAction(MotionEvent.ACTION_DOWN); + return dispatchTouchEvent(newEvent); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + float currentTouchY = ev.getY(); + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + mLastTouchY = currentTouchY; + break; + case MotionEvent.ACTION_MOVE: + float differentY = currentTouchY - mLastTouchY; + if (Math.abs(differentY) > mTouchSlop) { + if (!isHeaderViewCompleteInvisible() || (isContentViewToTop() && isHeaderViewCompleteInvisible() && mIsInControl)) { + mLastTouchY = currentTouchY; + return true; + } + } + break; + } + return super.onInterceptTouchEvent(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + initVelocityTrackerIfNotExists(); + mVelocityTracker.addMovement(event); + + float currentTouchY = event.getY(); + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (!mOverScroller.isFinished()) { + mOverScroller.abortAnimation(); + } + + mLastTouchY = currentTouchY; + break; + case MotionEvent.ACTION_MOVE: + float differentY = currentTouchY - mLastTouchY; + mLastTouchY = currentTouchY; + if (Math.abs(differentY) > 0) { + scrollBy(0, (int) -differentY); + } + break; + case MotionEvent.ACTION_CANCEL: + recycleVelocityTracker(); + if (!mOverScroller.isFinished()) { + mOverScroller.abortAnimation(); + } + break; + case MotionEvent.ACTION_UP: + mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int initialVelocity = (int) mVelocityTracker.getYVelocity(); + if ((Math.abs(initialVelocity) > mMinimumVelocity)) { + fling(-initialVelocity); + } + recycleVelocityTracker(); + break; + } + return true; + } + + public boolean isContentViewToTop() { + if (mDirectNormalView != null) { + return true; + } + + if (BGARefreshScrollingUtil.isScrollViewOrWebViewToTop(mDirectWebView)) { + return true; + } + + if (BGARefreshScrollingUtil.isScrollViewOrWebViewToTop(mDirectScrollView)) { + return true; + } + + if (BGARefreshScrollingUtil.isAbsListViewToTop(mDirectAbsListView)) { + return true; + } + + if (BGARefreshScrollingUtil.isRecyclerViewToTop(mDirectRecyclerView)) { + return true; + } + + if (mDirectViewPager != null) { + return isViewPagerContentViewToTop(); + } + + return false; + } + + private boolean isViewPagerContentViewToTop() { + if (mNestedContentView == null) { + regetNestedContentView(); + } + + if (mDirectNormalView != null) { + return true; + } + + if (BGARefreshScrollingUtil.isScrollViewOrWebViewToTop(mNestedWebView)) { + return true; + } + + if (BGARefreshScrollingUtil.isScrollViewOrWebViewToTop(mNestedScrollView)) { + return true; + } + + if (BGARefreshScrollingUtil.isAbsListViewToTop(mNestedAbsListView)) { + return true; + } + + if (BGARefreshScrollingUtil.isRecyclerViewToTop(mNestedRecyclerView)) { + return true; + } + + return false; + } + + /** + * 閲嶆柊鑾峰彇宓屽鐨勫唴瀹硅鍥� + */ + private void regetNestedContentView() { + int currentItem = mDirectViewPager.getCurrentItem(); + PagerAdapter adapter = mDirectViewPager.getAdapter(); + if (adapter instanceof FragmentPagerAdapter || adapter instanceof FragmentStatePagerAdapter) { + Fragment item = (Fragment) adapter.instantiateItem(mDirectViewPager, currentItem); + mNestedContentView = item.getView(); + + // 娓呯┖涔嬪墠鐨� + mNestedNormalView = null; + mNestedAbsListView = null; + mNestedRecyclerView = null; + mNestedScrollView = null; + mNestedWebView = null; + + if (mNestedContentView instanceof AbsListView) { + mNestedAbsListView = (AbsListView) mNestedContentView; + mNestedAbsListView.setOnScrollListener(mLvOnScrollListener); + + if (!isHeaderViewCompleteInvisible()) { + mNestedAbsListView.setSelection(0); + } + } else if (mNestedContentView instanceof RecyclerView) { + mNestedRecyclerView = (RecyclerView) mNestedContentView; + mNestedRecyclerView.removeOnScrollListener(mRvOnScrollListener); + mNestedRecyclerView.addOnScrollListener(mRvOnScrollListener); + + if (!isHeaderViewCompleteInvisible()) { + mNestedRecyclerView.scrollToPosition(0); + } + } else if (mNestedContentView instanceof ScrollView) { + mNestedScrollView = (ScrollView) mNestedContentView; + + if (!isHeaderViewCompleteInvisible()) { + mNestedScrollView.scrollTo(mNestedScrollView.getScrollX(), 0); + } + } else if (mNestedContentView instanceof WebView) { + mNestedWebView = (WebView) mNestedContentView; + + if (!isHeaderViewCompleteInvisible()) { + mNestedWebView.scrollTo(mNestedWebView.getScrollX(), 0); + } + } else { + mNestedNormalView = mNestedContentView; + } + } else { + throw new IllegalStateException(BGAStickyNavLayout.class.getSimpleName() + "鐨勭涓変釜瀛愭帶浠朵负ViewPager鏃讹紝鍏禷dapter蹇呴』鏄疐ragmentPagerAdapter鎴栬�匜ragmentStatePagerAdapter"); + } + } + + public void setRefreshLayout(BGARefreshLayout refreshLayout) { + mRefreshLayout = refreshLayout; + } + + private RecyclerView.OnScrollListener mRvOnScrollListener = new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if ((newState == RecyclerView.SCROLL_STATE_IDLE || newState == RecyclerView.SCROLL_STATE_SETTLING) && mRefreshLayout != null && mRefreshLayout.shouldHandleRecyclerViewLoadingMore(recyclerView)) { + mRefreshLayout.beginLoadingMore(); + } + } + }; + + private AbsListView.OnScrollListener mLvOnScrollListener = new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView absListView, int scrollState) { + if ((scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_FLING) && mRefreshLayout != null && mRefreshLayout.shouldHandleAbsListViewLoadingMore(absListView)) { + mRefreshLayout.beginLoadingMore(); + } + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + } + }; + + public boolean shouldHandleLoadingMore() { + if (mRefreshLayout == null) { + return false; + } + + if (mDirectNormalView != null) { + return true; + } + + if (BGARefreshScrollingUtil.isWebViewToBottom(mDirectWebView)) { + return true; + } + + if (BGARefreshScrollingUtil.isScrollViewToBottom(mDirectScrollView)) { + return true; + } + + if (mDirectAbsListView != null) { + return mRefreshLayout.shouldHandleAbsListViewLoadingMore(mDirectAbsListView); + } + + if (mDirectRecyclerView != null) { + return mRefreshLayout.shouldHandleRecyclerViewLoadingMore(mDirectRecyclerView); + } + + if (mDirectViewPager != null) { + if (mNestedContentView == null) { + regetNestedContentView(); + } + + if (mNestedNormalView != null) { + return true; + } + + if (BGARefreshScrollingUtil.isWebViewToBottom(mNestedWebView)) { + return true; + } + + if (BGARefreshScrollingUtil.isScrollViewToBottom(mNestedScrollView)) { + return true; + } + + if (mNestedAbsListView != null) { + return mRefreshLayout.shouldHandleAbsListViewLoadingMore(mNestedAbsListView); + } + + if (mNestedRecyclerView != null) { + return mRefreshLayout.shouldHandleRecyclerViewLoadingMore(mNestedRecyclerView); + } + } + + return false; + } + + public void scrollToBottom() { + BGARefreshScrollingUtil.scrollToBottom(mDirectScrollView); + BGARefreshScrollingUtil.scrollToBottom(mDirectRecyclerView); + BGARefreshScrollingUtil.scrollToBottom(mDirectAbsListView); + + if (mDirectViewPager != null) { + if (mNestedContentView == null) { + regetNestedContentView(); + } + BGARefreshScrollingUtil.scrollToBottom(mNestedScrollView); + BGARefreshScrollingUtil.scrollToBottom(mNestedRecyclerView); + BGARefreshScrollingUtil.scrollToBottom(mNestedAbsListView); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/HDLRefreshView.java b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/HDLRefreshView.java new file mode 100644 index 0000000..4f0cd09 --- /dev/null +++ b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/HDLRefreshView.java @@ -0,0 +1,127 @@ +/** + * Copyright 2015 bingoogolapple + * <p/> + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hdl.photovoltaic.widget.refreshlayout; + +import android.content.Context; +import android.graphics.drawable.AnimationDrawable; +import android.util.AttributeSet; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import androidx.annotation.DrawableRes; +import androidx.core.view.ViewCompat; + +import com.hdl.photovoltaic.R; + + +public class HDLRefreshView extends RelativeLayout { + private ImageView mPullDownView; + private ImageView mReleaseRefreshingView; + + private AnimationDrawable mChangeToReleaseRefreshAd; + private AnimationDrawable mRefreshingAd; + + private int mChangeToReleaseRefreshAnimResId; + private int mRefreshingAnimResId; + + public HDLRefreshView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mPullDownView = (ImageView) findViewById(R.id.iv_pull_down); + mReleaseRefreshingView = (ImageView) findViewById(R.id.iv_release_refreshing); + } + + public void setPullDownImageResource(@DrawableRes int resId) { + mPullDownView.setImageResource(resId); + } + + public void setChangeToReleaseRefreshAnimResId(@DrawableRes int resId) { + mChangeToReleaseRefreshAnimResId = resId; + mReleaseRefreshingView.setImageResource(mChangeToReleaseRefreshAnimResId); + } + + public void setRefreshingAnimResId(@DrawableRes int resId) { + mRefreshingAnimResId = resId; + } + + public void handleScale(float scale) { + scale = 0.1f + 0.9f * scale; + + ViewCompat.setPivotX(mPullDownView, mPullDownView.getWidth() * 0.5f); + ViewCompat.setPivotY(mPullDownView, mPullDownView.getHeight() * 0.5f); + ViewCompat.setScaleX(mPullDownView, scale); + ViewCompat.setScaleY(mPullDownView, scale); + } + + public void changeToIdle() { + + stopChangeToReleaseRefreshAd(); + stopRefreshingAd(); + + mPullDownView.setVisibility(VISIBLE); + mReleaseRefreshingView.setVisibility(INVISIBLE); + } + + public void changeToPullDown() { + mPullDownView.setVisibility(VISIBLE); + mReleaseRefreshingView.setVisibility(INVISIBLE); + } + + public void changeToReleaseRefresh() { + mReleaseRefreshingView.setImageResource(mChangeToReleaseRefreshAnimResId); + mChangeToReleaseRefreshAd = (AnimationDrawable) mReleaseRefreshingView.getDrawable(); + + mReleaseRefreshingView.setVisibility(VISIBLE); + mPullDownView.setVisibility(INVISIBLE); + + mChangeToReleaseRefreshAd.start(); + } + + public void changeToRefreshing() { + stopChangeToReleaseRefreshAd(); + + mReleaseRefreshingView.setImageResource(mRefreshingAnimResId); + mRefreshingAd = (AnimationDrawable) mReleaseRefreshingView.getDrawable(); + + mReleaseRefreshingView.setVisibility(VISIBLE); + mPullDownView.setVisibility(INVISIBLE); + + mRefreshingAd.start(); + } + + public void onEndRefreshing() { + stopChangeToReleaseRefreshAd(); + stopRefreshingAd(); + } + + private void stopRefreshingAd() { + if (mRefreshingAd != null) { + mRefreshingAd.stop(); + mRefreshingAd = null; + } + } + + private void stopChangeToReleaseRefreshAd() { + if (mChangeToReleaseRefreshAd != null) { + mChangeToReleaseRefreshAd.stop(); + mChangeToReleaseRefreshAd = null; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/HDLRefreshViewHolder.java b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/HDLRefreshViewHolder.java new file mode 100644 index 0000000..ad01418 --- /dev/null +++ b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/HDLRefreshViewHolder.java @@ -0,0 +1,131 @@ +/** + * Copyright 2015 bingoogolapple + * <p/> + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hdl.photovoltaic.widget.refreshlayout; + +import android.content.Context; +import android.graphics.Color; +import android.view.View; + +import androidx.annotation.DrawableRes; + +import com.hdl.photovoltaic.R; + + +public class HDLRefreshViewHolder extends BGARefreshViewHolder { + private HDLRefreshView mRefreshView; + private int mPullDownImageResId = -1; + private int mChangeToReleaseRefreshAnimResId = -1; + private int mRefreshingAnimResId = -1; + + /** + * @param context + * @param isLoadingMoreEnabled 涓婃媺鍔犺浇鏇村鏄惁鍙敤 + */ + public HDLRefreshViewHolder(Context context, boolean isLoadingMoreEnabled) { + super(context, isLoadingMoreEnabled); + } + + /** + * 璁剧疆涓嬫媺杩囩▼涓殑鍥剧墖璧勬簮 + * + * @param resId + */ + public void setPullDownImageResource(@DrawableRes int resId) { + mPullDownImageResId = resId; + } + + /** + * 璁剧疆杩涘叆閲婃斁鍒锋柊鐘舵�佹椂鐨勫姩鐢昏祫婧� + * + * @param resId + */ + public void setChangeToReleaseRefreshAnimResId(@DrawableRes int resId) { + mChangeToReleaseRefreshAnimResId = resId; + } + + /** + * 璁剧疆姝e湪鍒锋柊鏃剁殑鍔ㄧ敾璧勬簮 + * + * @param resId + */ + public void setRefreshingAnimResId(@DrawableRes int resId) { + mRefreshingAnimResId = resId; + } + + @Override + public View getRefreshHeaderView() { + if (mRefreshHeaderView == null) { + mRefreshHeaderView = View.inflate(mContext, R.layout.view_refresh_header, null); + mRefreshHeaderView.setBackgroundColor(Color.TRANSPARENT); + if (mRefreshViewBackgroundColorRes != -1) { + mRefreshHeaderView.setBackgroundResource(mRefreshViewBackgroundColorRes); + } + if (mRefreshViewBackgroundDrawableRes != -1) { + mRefreshHeaderView.setBackgroundResource(mRefreshViewBackgroundDrawableRes); + } + + mRefreshView = (HDLRefreshView) mRefreshHeaderView.findViewById(R.id.refreshView); + if (mPullDownImageResId != -1) { + mRefreshView.setPullDownImageResource(mPullDownImageResId); + } else { + throw new RuntimeException("璇疯皟鐢�" + HDLRefreshViewHolder.class.getSimpleName() + "鐨剆etPullDownImageResource鏂规硶璁剧疆涓嬫媺杩囩▼涓殑鍥剧墖璧勬簮"); + } + if (mChangeToReleaseRefreshAnimResId != -1) { + mRefreshView.setChangeToReleaseRefreshAnimResId(mChangeToReleaseRefreshAnimResId); + } else { + throw new RuntimeException("璇疯皟鐢�" + HDLRefreshViewHolder.class.getSimpleName() + "鐨剆etChangeToReleaseRefreshAnimResId鏂规硶璁剧疆杩涘叆閲婃斁鍒锋柊鐘舵�佹椂鐨勫姩鐢昏祫婧�"); + } + if (mRefreshingAnimResId != -1) { + mRefreshView.setRefreshingAnimResId(mRefreshingAnimResId); + } else { + throw new RuntimeException("璇疯皟鐢�" + HDLRefreshViewHolder.class.getSimpleName() + "鐨剆etRefreshingAnimResId鏂规硶璁剧疆姝e湪鍒锋柊鏃剁殑鍔ㄧ敾璧勬簮"); + } + } + return mRefreshHeaderView; + } + + @Override + public void handleScale(float scale, int moveYDistance) { + if (scale <= 1.0f) { + mRefreshView.handleScale(scale); + } + } + + @Override + public void changeToIdle() { + mRefreshView.changeToIdle(); + } + + @Override + public void changeToPullDown() { + mRefreshView.changeToPullDown(); + } + + @Override + public void changeToReleaseRefresh() { + mRefreshView.changeToReleaseRefresh(); + } + + @Override + public void changeToRefreshing() { + mRefreshView.changeToRefreshing(); + } + + @Override + public void onEndRefreshing() { + mRefreshView.onEndRefreshing(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/NestedScrollLayout.java b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/NestedScrollLayout.java new file mode 100644 index 0000000..d008102 --- /dev/null +++ b/app/src/main/java/com/hdl/photovoltaic/widget/refreshlayout/NestedScrollLayout.java @@ -0,0 +1,152 @@ +package com.hdl.photovoltaic.widget.refreshlayout; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.widget.NestedScrollView; +import androidx.recyclerview.widget.RecyclerView; + +import io.dcloud.weex.FlingHelper; + + +public class NestedScrollLayout extends NestedScrollView { + private View topView; + private ViewGroup contentView; + private static final String TAG = "NestedScrollLayout"; + + public NestedScrollLayout(Context context) { + this(context, null); + init(); + } + + public NestedScrollLayout(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + init(); + } + + public NestedScrollLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + init(); + } + + public NestedScrollLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr); + init(); + } + + private FlingHelper mFlingHelper; + + int totalDy = 0; + /** + * 鐢ㄤ簬鍒ゆ柇RecyclerView鏄惁鍦╢ling + */ + boolean isStartFling = false; + /** + * 璁板綍褰撳墠婊戝姩鐨剏杞村姞閫熷害 + */ + private int velocityY = 0; + + private void init() { + mFlingHelper = new FlingHelper(getContext()); + setOnScrollChangeListener(new View.OnScrollChangeListener() { + @Override + public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { + if (isStartFling) { + totalDy = 0; + isStartFling = false; + } + if (scrollY == 0) { + Log.e(TAG, "TOP SCROLL"); + // refreshLayout.setEnabled(true); + } + if (scrollY == (getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight())) { + Log.e(TAG, "BOTTOM SCROLL"); + dispatchChildFling(); + } + //鍦≧ecyclerView fling鎯呭喌涓嬶紝璁板綍褰撳墠RecyclerView鍦▂杞寸殑鍋忕Щ + totalDy += scrollY - oldScrollY; + } + }); + } + + private void dispatchChildFling() { + if (velocityY != 0) { + Double splineFlingDistance = mFlingHelper.getSplineFlingDistance(velocityY); + if (splineFlingDistance > totalDy) { + childFling(mFlingHelper.getVelocityByDistance(splineFlingDistance - Double.valueOf(totalDy))); + } + } + totalDy = 0; + velocityY = 0; + } + + private void childFling(int velY) { + RecyclerView childRecyclerView = getChildRecyclerView(contentView); + if (childRecyclerView != null) { + childRecyclerView.fling(0, velY); + } + } + + @Override + public void fling(int velocityY) { + super.fling(velocityY); + if (velocityY <= 0) { + this.velocityY = 0; + } else { + isStartFling = true; + this.velocityY = velocityY; + } + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + topView = ((ViewGroup) getChildAt(0)).getChildAt(0); + contentView = (ViewGroup) ((ViewGroup) getChildAt(0)).getChildAt(1); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // 璋冩暣contentView鐨勯珮搴︿负鐖跺鍣ㄩ珮搴︼紝浣夸箣濉厖甯冨眬锛岄伩鍏嶇埗瀹瑰櫒婊氬姩鍚庡嚭鐜扮┖鐧� + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + ViewGroup.LayoutParams lp = contentView.getLayoutParams(); + lp.height = getMeasuredHeight(); + contentView.setLayoutParams(lp); + } + + /** + * 瑙e喅婊戝姩鍐茬獊锛歊ecyclerView鍦ㄦ粦鍔ㄤ箣鍓嶄細闂笅鐖跺竷灞�鏄惁闇�瑕佹嫤鎴紝鐖跺竷灞�浣跨敤姝ゆ柟娉� + */ + @Override + public void onNestedPreScroll(@NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) { +// Log.e("NestedScrollLayout", getScrollY() + "::onNestedPreScroll::" + topView.getMeasuredHeight() + "::dy::" + dy); + // 鍚戜笂婊戝姩銆傝嫢褰撳墠topview鍙锛岄渶瑕佸皢topview婊戝姩鑷充笉鍙 + boolean hideTop = dy > 0 && getScrollY() < topView.getMeasuredHeight(); + if (hideTop) { + scrollBy(0, dy); + // 杩欎釜鏄娑堣垂鐨勮窛绂伙紝濡傛灉娌℃湁浼氳閲嶅娑堣垂锛岀幇璞℃槸鐖跺竷灞�涓庡瓙甯冨眬鍚屾椂婊戝姩 + consumed[1] = dy; + } + } + + private RecyclerView getChildRecyclerView(ViewGroup viewGroup) { + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View view = viewGroup.getChildAt(i); + if (view instanceof RecyclerView) { + return (RecyclerView) viewGroup.getChildAt(i); + } else if (viewGroup.getChildAt(i) instanceof ViewGroup) { + ViewGroup childRecyclerView = getChildRecyclerView((ViewGroup) viewGroup.getChildAt(i)); + if (childRecyclerView instanceof RecyclerView) { + return (RecyclerView) childRecyclerView; + } + } + continue; + } + return null; + } +} diff --git a/app/src/main/res/drawable-xhdpi/loading.gif b/app/src/main/res/drawable-xhdpi/loading_gif.gif similarity index 100% rename from app/src/main/res/drawable-xhdpi/loading.gif rename to app/src/main/res/drawable-xhdpi/loading_gif.gif Binary files differ diff --git a/app/src/main/res/drawable/loading_44.png b/app/src/main/res/drawable/loading_44.png new file mode 100644 index 0000000..3f9436a --- /dev/null +++ b/app/src/main/res/drawable/loading_44.png Binary files differ diff --git a/app/src/main/res/drawable/loading.png b/app/src/main/res/drawable/loading_gif.png similarity index 100% rename from app/src/main/res/drawable/loading.png rename to app/src/main/res/drawable/loading_gif.png Binary files differ diff --git a/app/src/main/res/drawable/loading_refresh.xml b/app/src/main/res/drawable/loading_refresh.xml new file mode 100644 index 0000000..b8bae38 --- /dev/null +++ b/app/src/main/res/drawable/loading_refresh.xml @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="utf-8"?> +<animation-list xmlns:android="http://schemas.android.com/apk/res/android" + android:oneshot="false"> + <item + android:drawable="@mipmap/loading_1" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_2"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_3"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_4"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_5"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_6"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_7" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_8"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_9"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_10"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_11"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_12"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_13" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_14"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_15"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_16"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_17"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_18"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_19" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_20"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_21"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_22"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_23"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_24"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_25" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_26"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_27"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_28"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_29"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_30"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_31" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_32"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_33"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_34"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_35"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_36"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_37" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_38"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_39"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_40"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_41"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_42"--> + <!-- android:duration="100" />--> +<!-- <item--> +<!-- android:drawable="@mipmap/loading_43"--> +<!-- android:duration="150" />--> + <item + android:drawable="@mipmap/loading_44" + android:duration="100" /> +</animation-list> \ No newline at end of file diff --git a/app/src/main/res/drawable/loading_refresh_end.xml b/app/src/main/res/drawable/loading_refresh_end.xml new file mode 100644 index 0000000..887e523 --- /dev/null +++ b/app/src/main/res/drawable/loading_refresh_end.xml @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="utf-8"?> +<animation-list xmlns:android="http://schemas.android.com/apk/res/android" + android:oneshot="false"> + + + <item + android:drawable="@mipmap/loading_44" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_2"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_3"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_4"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_5"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_6"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_37" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_8"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_9"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_10"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_11"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_12"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_31" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_14"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_15"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_16"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_17"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_18"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_25" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_20"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_21"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_22"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_23"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_24"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_19" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_26"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_27"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_28"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_29"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_30"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_31" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_32"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_33"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_34"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_35"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_36"--> + <!-- android:duration="100" />--> + <item + android:drawable="@mipmap/loading_37" + android:duration="100" /> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_38"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_39"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_40"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_41"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_42"--> + <!-- android:duration="100" />--> + <!-- <item--> + <!-- android:drawable="@mipmap/loading_43"--> + <!-- android:duration="150" />--> + <item + android:drawable="@mipmap/loading_44" + android:duration="100" /> +</animation-list> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home_page.xml b/app/src/main/res/layout/fragment_home_page.xml index 6b82695..29ece2d 100644 --- a/app/src/main/res/layout/fragment_home_page.xml +++ b/app/src/main/res/layout/fragment_home_page.xml @@ -37,8 +37,8 @@ android:src="@drawable/add" /> </RelativeLayout> - <androidx.swiperefreshlayout.widget.SwipeRefreshLayout - android:id="@+id/srl" + <com.hdl.photovoltaic.widget.refreshlayout.BGARefreshLayout + android:id="@+id/rsl" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginTop="@dimen/dp_10" @@ -952,7 +952,21 @@ </ScrollView> - </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> + </com.hdl.photovoltaic.widget.refreshlayout.BGARefreshLayout> + +<!-- <androidx.constraintlayout.widget.Guideline--> +<!-- android:id="@+id/guideline2"--> +<!-- android:layout_width="wrap_content"--> +<!-- android:layout_height="wrap_content"--> +<!-- android:orientation="horizontal"--> +<!-- app:layout_constraintGuide_begin="20dp" />--> + +<!-- <androidx.constraintlayout.widget.Guideline--> +<!-- android:id="@+id/guideline3"--> +<!-- android:layout_width="wrap_content"--> +<!-- android:layout_height="wrap_content"--> +<!-- android:orientation="vertical"--> +<!-- app:layout_constraintGuide_begin="20dp" />--> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/view_refresh_header.xml b/app/src/main/res/layout/view_refresh_header.xml new file mode 100644 index 0000000..bd1bab7 --- /dev/null +++ b/app/src/main/res/layout/view_refresh_header.xml @@ -0,0 +1,29 @@ +<?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="vertical"> + + <com.hdl.photovoltaic.widget.refreshlayout.HDLRefreshView + android:id="@+id/refreshView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="5dp" + android:layout_marginBottom="5dp"> + + <ImageView + android:id="@+id/iv_pull_down" + android:layout_width="@dimen/dp_60" + android:layout_height="@dimen/dp_36" + android:layout_centerInParent="true" /> + + <ImageView + android:id="@+id/iv_release_refreshing" + android:layout_width="@dimen/dp_60" + android:layout_height="@dimen/dp_36" + android:layout_centerInParent="true" + android:visibility="invisible" /> + </com.hdl.photovoltaic.widget.refreshlayout.HDLRefreshView> + +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/mipmap-xhdpi/loading_1.png b/app/src/main/res/mipmap-xhdpi/loading_1.png new file mode 100644 index 0000000..4e78b7e --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_1.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_10.png b/app/src/main/res/mipmap-xhdpi/loading_10.png new file mode 100644 index 0000000..2bf501f --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_10.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_11.png b/app/src/main/res/mipmap-xhdpi/loading_11.png new file mode 100644 index 0000000..cbebd1b --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_11.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_12.png b/app/src/main/res/mipmap-xhdpi/loading_12.png new file mode 100644 index 0000000..5792021 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_12.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_13.png b/app/src/main/res/mipmap-xhdpi/loading_13.png new file mode 100644 index 0000000..a717c3d --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_13.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_14.png b/app/src/main/res/mipmap-xhdpi/loading_14.png new file mode 100644 index 0000000..0ddcae8 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_14.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_15.png b/app/src/main/res/mipmap-xhdpi/loading_15.png new file mode 100644 index 0000000..907c8cd --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_15.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_16.png b/app/src/main/res/mipmap-xhdpi/loading_16.png new file mode 100644 index 0000000..dbd7268 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_16.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_17.png b/app/src/main/res/mipmap-xhdpi/loading_17.png new file mode 100644 index 0000000..3b020aa --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_17.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_18.png b/app/src/main/res/mipmap-xhdpi/loading_18.png new file mode 100644 index 0000000..4d225a2 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_18.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_19.png b/app/src/main/res/mipmap-xhdpi/loading_19.png new file mode 100644 index 0000000..2e38281 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_19.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_2.png b/app/src/main/res/mipmap-xhdpi/loading_2.png new file mode 100644 index 0000000..8b727b1 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_2.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_20.png b/app/src/main/res/mipmap-xhdpi/loading_20.png new file mode 100644 index 0000000..aef3bdb --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_20.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_21.png b/app/src/main/res/mipmap-xhdpi/loading_21.png new file mode 100644 index 0000000..56005d2 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_21.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_22.png b/app/src/main/res/mipmap-xhdpi/loading_22.png new file mode 100644 index 0000000..1e2a20c --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_22.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_23.png b/app/src/main/res/mipmap-xhdpi/loading_23.png new file mode 100644 index 0000000..42cfcbd --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_23.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_24.png b/app/src/main/res/mipmap-xhdpi/loading_24.png new file mode 100644 index 0000000..056d0ff --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_24.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_25.png b/app/src/main/res/mipmap-xhdpi/loading_25.png new file mode 100644 index 0000000..e4406a7 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_25.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_26.png b/app/src/main/res/mipmap-xhdpi/loading_26.png new file mode 100644 index 0000000..7365a21 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_26.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_27.png b/app/src/main/res/mipmap-xhdpi/loading_27.png new file mode 100644 index 0000000..c0fc4b4 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_27.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_28.png b/app/src/main/res/mipmap-xhdpi/loading_28.png new file mode 100644 index 0000000..02bce66 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_28.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_29.png b/app/src/main/res/mipmap-xhdpi/loading_29.png new file mode 100644 index 0000000..68fc843 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_29.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_3.png b/app/src/main/res/mipmap-xhdpi/loading_3.png new file mode 100644 index 0000000..0703a42 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_3.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_30.png b/app/src/main/res/mipmap-xhdpi/loading_30.png new file mode 100644 index 0000000..bd28c80 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_30.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_31.png b/app/src/main/res/mipmap-xhdpi/loading_31.png new file mode 100644 index 0000000..af24d4d --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_31.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_32.png b/app/src/main/res/mipmap-xhdpi/loading_32.png new file mode 100644 index 0000000..d1eaa2f --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_32.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_33.png b/app/src/main/res/mipmap-xhdpi/loading_33.png new file mode 100644 index 0000000..dccaa4f --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_33.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_34.png b/app/src/main/res/mipmap-xhdpi/loading_34.png new file mode 100644 index 0000000..7a5f5e1 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_34.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_35.png b/app/src/main/res/mipmap-xhdpi/loading_35.png new file mode 100644 index 0000000..67b391a --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_35.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_36.png b/app/src/main/res/mipmap-xhdpi/loading_36.png new file mode 100644 index 0000000..71ae83e --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_36.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_37.png b/app/src/main/res/mipmap-xhdpi/loading_37.png new file mode 100644 index 0000000..dd0a053 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_37.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_38.png b/app/src/main/res/mipmap-xhdpi/loading_38.png new file mode 100644 index 0000000..2284af6 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_38.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_39.png b/app/src/main/res/mipmap-xhdpi/loading_39.png new file mode 100644 index 0000000..ae7f026 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_39.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_4.png b/app/src/main/res/mipmap-xhdpi/loading_4.png new file mode 100644 index 0000000..a04b9f3 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_4.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_40.png b/app/src/main/res/mipmap-xhdpi/loading_40.png new file mode 100644 index 0000000..87a6211 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_40.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_41.png b/app/src/main/res/mipmap-xhdpi/loading_41.png new file mode 100644 index 0000000..36bfe1b --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_41.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_42.png b/app/src/main/res/mipmap-xhdpi/loading_42.png new file mode 100644 index 0000000..053d8e4 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_42.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_43.png b/app/src/main/res/mipmap-xhdpi/loading_43.png new file mode 100644 index 0000000..e5e1102 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_43.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_44.png b/app/src/main/res/mipmap-xhdpi/loading_44.png new file mode 100644 index 0000000..3f9436a --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_44.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_5.png b/app/src/main/res/mipmap-xhdpi/loading_5.png new file mode 100644 index 0000000..0461f4f --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_5.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_6.png b/app/src/main/res/mipmap-xhdpi/loading_6.png new file mode 100644 index 0000000..06ba20c --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_6.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_7.png b/app/src/main/res/mipmap-xhdpi/loading_7.png new file mode 100644 index 0000000..fa39815 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_7.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_8.png b/app/src/main/res/mipmap-xhdpi/loading_8.png new file mode 100644 index 0000000..8bceb47 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_8.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/loading_9.png b/app/src/main/res/mipmap-xhdpi/loading_9.png new file mode 100644 index 0000000..d799165 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/loading_9.png Binary files differ -- Gitblit v1.8.0