The TwinklingRefreshLayout extends Google’s SwipeRefreshLayout idea by not cutting on the list controls, but using a ViewGroup to contain the list controls to keep them low coupling and versatile. Its main features are:
- Support RecyclerView, ScrollView, AbsListView series (ListView, GridView), WebView and other controls that can get scrollY
- Support for loading more
- Default support for out-of-bounds rebound
- Enable clean out-of-bounds rebound mode with no refresh control
- SetOnRefreshListener has a number of methods that can be called back
- Header and Footer are abstracted as interfaces, and coefficients in the sliding process are called back to make it easy to personalize Header and Footer
Demo
Method of use
Copy the Libray module into your project, or rely on it directly in build.gradle:
The compile 'com. Lcodecorex: tkrefreshlayout: 1.0.1'
Copy the code
2. Add TwinklingRefreshLayout to the XML
Copy the code
TwinklingRefreshLayout does not automatically end up refreshing or loading more, requiring manual control
refreshLayout.setOnRefreshListener(new TwinklingRefreshLayout.OnRefreshListener(){
@Override
public void onRefresh(final TwinklingRefreshLayout refreshLayout) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
refreshLayout.finishRefreshing();
}
},2000);
}
@Override
public void onLoadMore(final TwinklingRefreshLayout refreshLayout) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
refreshLayout.finishLoadmore();
}
},2000);
}
});
}Copy the code
Finish the refresh using the finishRefreshing() method and finish loading more using the finishLoadmore() method. There are other methods for OnRefreshListener here, and you can override them as needed.
- SetWaveHeight Sets the maximum stretchable height of the head.
- SetHeaderHeight Fixed head height (display refresh status at this height)
- SetBottomHeight Bottom height
SetHeaderView (IHeaderView, headerView), setBottomView(IBottomView, bottomView)
Set the header/bottom personalization refresh effect. The header needs to implement IHeaderView, and the bottom needs to implement IBottomView.
The refresh control is not displayed when the Fling is not in bounds. The Header and Footer are displayed when the Fling is not in bounds. There may be special cases where the refresh control will affect the display experience before setting this state.
setPureScrollModeOn()
Turn on the pure bounding rebound mode, that is, all views related to refresh are not displayed, only the bounding rebound effect is displayed
- Tr_wave_height Maximum head stretching height
- Tr_head_height Head height
- Tr_bottom_height Bottom height
Additional attributes will be considered, such as the ability to set the layout of the header or footer in XML.
Other instructions
Many refresh controls like SwipeRefreshLayout don't do this, including SwipeRefreshLayout, because the unintercepted time is passed to the list control, whose scroll state is hard to get. The solution is to set the OnTouchListener to the list control and send the event to the GestureDetector to handle. Then, the list control's OnScrollListener will listen to see if the View has been scrolled to the top Slightly).
2. SetOnRefreshListener A number of callback methods
- OnPullingDown (TwinklingRefreshLayout refreshLayout, Float Fraction) is being pulled down
- OnPullingUp (TwinklingRefreshLayout refreshLayout, Float Fraction) is being pulled up
- OnPullDownReleasing (TwinklingRefreshLayout refreshLayout, float Fraction) Drop down release process
- OnPullUpReleasing (TwinklingRefreshLayout refreshLayout, Float Fraction) PulluPreLeasing (TwinklingRefreshLayout, Float Fraction
- OnRefresh (TwinklingRefreshLayout refreshLayout) is refreshing
- OnLoadMore (TwinklingRefreshLayout refreshLayout) is loading more
Fraction represents the ratio of the current pull-down distance to the Header height (or the ratio of the current pull-up distance to the Footer height).
The implemented headers include BezierLayout(Figure 1), GoogleDotView(Figure 2) and SinaRefreshView(Figure 3). The Footer is BottomProgressView(FIG. 1) and LoadingView(FIG. 3). For more dynamic effects, you can refer to AVLoadingIndicatorView library.
The first picture is from BeautifulRefreshForGirl. The original dynamic effect only supports version 21 and above, and the View disappears during the sliding process. The author made some optimizations to make it work in the interface normally.
3. Implement personalized headers and footers
The relevant interfaces are IHeaderView and IBottomView respectively, and the codes are as follows:
public interface IHeaderView {
View getView();
void onPullingDown(float fraction,float maxHeadHeight,float headHeight);
void onPullReleasing(float fraction,float maxHeadHeight,float headHeight);
void startAnim(float maxHeadHeight,float headHeight);
}Copy the code
The getView() method is used to get the actual Header in TwinklingRefreshLayout, so null cannot be returned.
To achieve the refresh effect like Sina Weibo, the implementation code is as follows:
1. First define SinaRefreshHeader inherits from FrameLayout and implements IHeaderView
2. The getView() method returns this
3. Get the layout you need in the onAttachedToWindow() method
@Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (rootView == null) { rootView = View.inflate(getContext(), R.layout.view_sinaheader, null); refreshArrow = (ImageView) rootView.findViewById(R.id.iv_arrow); refreshTextView = (TextView) rootView.findViewById(R.id.tv); loadingView = (ImageView) rootView.findViewById(R.id.iv_loading); addView(rootView); }}Copy the code
4. Implement other methods
@Override
public void onPullingDown(float fraction, float maxHeadHeight, float headHeight) {
if (fraction < 1f) refreshTextView.setText(pullDownStr);
if (fraction > 1f) refreshTextView.setText(releaseRefreshStr);
refreshArrow.setRotation(fraction * headHeight / maxHeadHeight * 180);
}
@Override
public void onPullReleasing(float fraction, float maxHeadHeight, float headHeight) {
if (fraction < 1f) {
refreshTextView.setText(pullDownStr);
refreshArrow.setRotation(fraction * headHeight / maxHeadHeight * 180);
if (refreshArrow.getVisibility() == GONE) {
refreshArrow.setVisibility(VISIBLE);
loadingView.setVisibility(GONE);
}
}
}
@Override
public void startAnim(float maxHeadHeight, float headHeight) {
refreshTextView.setText(refreshingStr);
refreshArrow.setVisibility(GONE);
loadingView.setVisibility(VISIBLE);
}Copy the code
5. Layout files
Copy the code
Refresharrow.setrotation (fraction * headHeight/maxHeadHeight * 180) Fraction * headHeight represents the current sliding distance of the head, then calculate the ratio of this to the maximum height, then multiply by 180, so that when the Arrow reaches the maximum sliding distance, the Arrow will rotate exactly 180 degrees.
OnPullingDown/onPullingUp said is dropdown/is on the drawing process. OnPullReleasing indicates the state of the callback when pulling up/down. StartAnim is called back after onRefresh/onLoadMore.
As shown above, it's easy to implement a personalized Header or Footer. For a simpler implementation, see TextHeaderView in Demo (Figure 4).
- The solution needs to be optimized by setting layoutparams.height =0.
- Optimize custom loading dynamics.
- Optimize code quality.
- Make a star related motion effect.
- Some optimizations for rebound effects, such as support for different interpolators