以下のレイアウトでSwipeRefreshLayout
を使用しています:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:background="@color/homePageBackground"
Android:orientation="vertical" >
<Android.support.v4.widget.SwipeRefreshLayout
Android:id="@+id/swipeRefreshLayout_listView"
Android:layout_width="match_parent"
Android:layout_height="match_parent" >
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical" >
<fragment
Android:id="@+id/announcementHomefragment"
Android:name="in.test.app.AnnouncementFragment"
Android:layout_width="match_parent"
Android:layout_height="wrap_content" />
<ScrollView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="@color/homePageBackground" >
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginBottom="15dp"
Android:background="@color/homePageBackground" >
<TextView
Android:id="@+id/newsTitle"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_marginLeft="15dp"
Android:layout_marginTop="5dp"
Android:gravity="center"
Android:text="@string/new_list"
Android:textAppearance="?android:attr/textAppearanceSmall"
Android:textColor="@color/white"
Android:textStyle="bold" />
<fragment
Android:id="@+id/newshomefragment"
Android:name="in.test.app.NewsFragment"
Android:layout_width="wrap_content"
Android:layout_height="190dp"
Android:layout_below="@id/newsTitle"
Android:layout_marginTop="-15dp" />
<TextView
Android:id="@+id/productTitle"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_below="@id/newshomefragment"
Android:layout_gravity="center"
Android:layout_marginLeft="15dp"
Android:layout_marginTop="5dp"
Android:gravity="center"
Android:text="@string/product_in_home"
Android:textAppearance="?android:attr/textAppearanceSmall"
Android:textColor="@color/white"
Android:textStyle="bold" />
<fragment
Android:id="@+id/proCategoryhomefragment"
Android:name="in.test.app.CategoryFragment"
Android:layout_width="wrap_content"
Android:layout_height="170dp"
Android:layout_below="@id/productTitle"
Android:layout_marginTop="-15dp" />
<TextView
Android:id="@+id/trainingTitle"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_below="@id/proCategoryhomefragment"
Android:layout_gravity="center"
Android:layout_marginLeft="15dp"
Android:layout_marginTop="2dp"
Android:gravity="center"
Android:text="@string/trainings_in_home"
Android:textAppearance="?android:attr/textAppearanceSmall"
Android:textColor="@color/white"
Android:textStyle="bold" />
<fragment
Android:id="@+id/trainingfragment"
Android:name="in.test.app.TrainingFragment"
Android:layout_width="match_parent"
Android:layout_height="180dp"
Android:layout_below="@id/trainingTitle"
Android:layout_marginBottom="10dp"
Android:layout_marginTop="-15dp" />
</RelativeLayout>
</ScrollView>
</LinearLayout>
</Android.support.v4.widget.SwipeRefreshLayout>
SwipeRefreshLayout
をプルダウンすると機能しますが、上記のコードを見るとわかるように、内部にスクロールビューがあります。したがって、スクロールビューをプルダウンすると、スクロールビューがダウンし、下に移動したために画像の半分が表示されません。もう一度プルアップしようとすると、スクロールビューが表示されません。代わりに、SwipeRefreshLayout
が呼び出されます。私は何をすべきか?
私を助けてください。
このレイアウトを表示するクラスからさまざまな条件を追加できるようにするには、リスナー付きの拡張SwipeRefreshLayoutを使用する方がよいと思います。
次のようなもの:GeneralSwipeRefreshLayout.Java
public class GeneralSwipeRefreshLayout extends SwipeRefreshLayout {
private OnChildScrollUpListener mScrollListenerNeeded;
public interface OnChildScrollUpListener {
boolean canChildScrollUp();
}
public GeneralSwipeRefreshLayout(Context context) {
super(context);
}
public GeneralSwipeRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* Listener that controls if scrolling up is allowed to child views or not
*/
public void setOnChildScrollUpListener(OnChildScrollUpListener listener) {
mScrollListenerNeeded = listener;
}
@Override
public boolean canChildScrollUp() {
if (mScrollListenerNeeded == null) {
Log.e(GeneralSwipeRefreshLayout.class.getSimpleName(), "listener is not defined!");
}
return mScrollListenerNeeded != null && mScrollListenerNeeded.canChildScrollUp();
}
}
次に、ListViewまたはGridViewレイアウトを含むSwipeRefreshLayoutを表示するクラス内で、次のようなことができます。
mSwipeLayout.setOnChildScrollUpListener(new OnChildScrollUpListener() {
@Override
public boolean canChildScrollUp() {
return mListView.getFirstVisiblePosition() > 0 ||
mListView.getChildAt(0) == null ||
mListView.getChildAt(0).getTop() < 0;
}
});
extendsSwipeRefreshLayout
およびoverrideメソッドcanChildScrollUp()
のクラスを作成するだけです。コントロールを下にスクロールする場合はtrueを返します。
たとえば、scrollviewの場合、これを試すことができます。
@override.
boolean canChildScrollUp()
{
//your condition to check scrollview reached at top while scrolling
if(scrollview.getScrollY() == 0.0)
return true;
else
return false;
}
他の人がすでに述べたように、SwipeRefreshLayoutの直接の子としてスクロール可能なビュー(つまり、リストビュー)がない場合、在庫のcanChildScrollUpは機能しません。
子ビューのスクロール機能のチェックでSwipeRefreshLayoutが使用する単純なロジックと関係があります。
私はActionbarActivity内でListViewを使用していて、リストビューが空のときは常に空のビューを含めたいと思っていました。 SwipeRefreshLayoutクラスは子を1つしか持つことができないため、これにより問題が発生しました。また、この子のscrollUp機能をチェックして、プルダウンによって子がscrollUpになるか、または子のコンテンツが更新されるかを判別します。
したがって、SwipeRefreshLayoutと同じロジックを使用する場合は、クラスを拡張し、スクロール可能なビューにハンドルを渡すことができるメソッドを作成します。ストックの実装ではcanScrollVertically()を使用していますが、これはまさに私たちが望むことを行いますが、SDK> = 14でのみ表示されます。
また、クラスを拡張するときは、パラメーター「AttributeSet」を含むコンストラクターを含めることを忘れないでください。そうしないと、レイアウトファイルでクラスを使用するときに問題が発生します。
したがって、リストビューを含むアクティビティ(この場合はActionBarActivity)のonCreateメソッドで、ListViewまたはスクロールに使用するビューを渡してsetMyScrollableViewを呼び出すだけです。
/*Constructor*/
public MySwipeRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
View mMyScrollableView = null; //The content that get's pulled down.
/*Method used to pass in my scrollable view*/
public void setMyScrollableView(View view){
mMyScrollableView = view;
}
/**
* @return Whether it is possible for the child view of this layout to
* scroll up. This was taken for the most part directly from SwipeRefreshLayout
*/
public boolean canChildScrollUp() {
if(mMyScrollableView == null)
return false;
if (Android.os.Build.VERSION.SDK_INT < 14) {
if (mMyScrollableView instanceof AbsListView) {
final AbsListView absListView = (AbsListView) mMyScrollableView;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
.getTop() < absListView.getPaddingTop());
} else {
return mMyScrollableView.getScrollY() > 0;
}
} else {
return ViewCompat.canScrollVertically(mMyScrollableView, -1);
}
}
@ User22791のソリューションは完全に機能し、それに基づいて、githubで使用可能なライブラリを作成しました。これを使用して(そして変更して)、開発者がswipeRefreshLayoutを簡単に使用できるようにします。それはここにあります: https://github.com/dagova/referencedSwipeRefreshLayout
基本的には、canChildScrollUpメソッドでチェックするビューをレイアウトで参照する必要があります。お役に立てれば幸いです。
より簡単な解決策は、onScrollListener
を使用して、ユーザーがfirstElementを表示できるかどうかを確認することです。
someView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
if (isViewAtTop()) {
swipeLayout.setEnabled(true);
} else {
swipeLayout.setEnabled(false);
}
}
}
@Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem == 0) {
swipeLayout.setEnabled(true);
} else {
swipeLayout.setEnabled(false);
}
}
});
メソッドisViewAtTop()は他のいくつかのメソッドであり、このビューが最上部にスクロールされていることを確認します
他の回答もうまくいかないこともわかりました。
彼らがメソッドgetScrollY()
を使用していることを理解するために少し頭を悩ませました-これは this answer が説明しているように、これまでのView
メソッドですScrollコンテナがどれだけスクロールされたかを示す方法ではなく、コンテナ内でスクロールします。
他の回答と同じ手法を使用する場合(canChildScrollUp()
メソッドをオーバーライド)、Scrollableがその最高点にあるかどうかを簡単に確認できます。
@Override
public boolean canChildScrollUp() {
return !isListAtTop();
}
private boolean isListAtTop() {
if(mGridView.getChildCount() == 0) return true;
return mGridView.getChildAt(0).getTop() == 0;
}
(ご覧のとおり、私はGridView
を使用していますが、ListView
も使用できます)
わかりました。 SwipeRefreshLayout
がレイアウトのルートであり、ScrollView
が階層の深い場所にある場合(私はScrollView
をRelativeLayout
の中に入れました)、 SwipeRefreshLayout
の直接の子である場合、ScrollView
のスワイプが適切に検出されません。
SwipeRefreshLayout
を拡張するカスタムクラスを作成し、SwipRefreshLayout
のcanChildScrollUp()
メソッドをオーバーライドする必要があります
次に例を示します。
public class CustomSwipeRefreshLayout extends SwipeRefreshLayout {
private ScrollView scrollview;
public CustomSwipeRefreshLayout(Context context) {
super(context);
}
public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setView(ScrollView view) {
this.scrollview = view;
}
@Override
public boolean canChildScrollUp() {
return scrollview.getScrollY() != 0;
}
}