Eu implementei SwipeRefreshLayout
e ViewPager
em meu aplicativo, mas há um grande problema: sempre que vou deslizar para a esquerda / direita para alternar entre as páginas, a rolagem é muito sensível. Um pequeno deslizar para baixo também acionará a SwipeRefreshLayout
atualização.
Quero definir um limite para o início do deslizamento horizontal e, em seguida, forçar na horizontal apenas até o final do deslizamento. Em outras palavras, desejo cancelar o deslizamento vertical quando o dedo estiver se movendo horizontalmente.
Esse problema ocorre apenas em ViewPager
, se eu deslizar para baixo e a SwipeRefreshLayout
função de atualização for acionada (a barra é mostrada) e, em seguida, mover meu dedo horizontalmente, ainda permite apenas deslizamentos verticais.
Tentei estender a ViewPager
aula, mas não está funcionando de jeito nenhum:
public class CustomViewPager extends ViewPager {
public CustomViewPager(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean in = super.onInterceptTouchEvent(ev);
if (in) {
getParent().requestDisallowInterceptTouchEvent(true);
this.requestDisallowInterceptTouchEvent(true);
}
return false;
}
}
Layout xml:
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/viewTopic"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.myapp.listloader.foundation.CustomViewPager
android:id="@+id/topicViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
qualquer ajuda seria apreciada, obrigado
fonte
SwipeRefreshLayout
?Respostas:
Não tenho certeza se você ainda tem esse problema, mas o aplicativo Google I / O iosched resolve o problema da seguinte maneira:
Eu usei o mesmo e funciona muito bem.
EDIT: Use addOnPageChangeListener () em vez de setOnPageChangeListener ().
fonte
Resolvido de forma muito simples, sem estender nada
trabalhe como um encanto
fonte
View
que possa ter dentro deViewPager
, poisSwipeRefreshLayout
permite até mesmo a rolagem vertical apenas para seu filho de nível superior (e em APIs inferiores a ICS apenas se for umListView
) .ViewPager
dentroSwipeRefrestLayout
e o ViewPager temListview
!SwipeRefreshLayout
deixe-me rolar para baixo, mas ao rolar para cima isso aciona o progresso da atualização. Alguma sugestão?Eu conheci seu problema. Personalizar o SwipeRefreshLayout resolveria o problema.
Veja a referência: link
fonte
Eu baseei isso em uma resposta anterior, mas achei que funcionava um pouco melhor. O movimento começa com um evento ACTION_MOVE e termina em ACTION_UP ou ACTION_CANCEL na minha experiência.
fonte
Por algum motivo mais conhecido apenas por eles, a equipe de desenvolvedores da biblioteca de suporte decidiu interceptar à força todos os eventos de movimento de arrastar vertical do
SwipeRefreshLayout
layout filho, mesmo quando uma criança solicita especificamente a propriedade do evento. A única coisa que eles verificam é se o estado de rolagem vertical de seu filho principal está em zero (no caso de seu filho ser rolável verticalmente). OrequestDisallowInterceptTouchEvent()
método foi substituído por um corpo vazio e o (nem tanto) comentário esclarecedor "Não".A maneira mais fácil de resolver esse problema seria apenas copiar a classe da biblioteca de suporte em seu projeto e remover a substituição do método.
ViewGroup
A implementação de usa estado interno para manipulaçãoonInterceptTouchEvent()
, portanto, você não pode simplesmente sobrescrever o método novamente e duplicá-lo. Se você realmente deseja sobrescrever a implementação da biblioteca de suporte, então você terá que configurar um sinalizador customizado nas chamadas pararequestDisallowInterceptTouchEvent()
, e sobrescreveronInterceptTouchEvent()
eonTouchEvent()
(ou possivelmente hackearcanChildScrollUp()
) o comportamento baseado nisso.fonte
Eu encontrei uma solução para ViewPager2. Eu uso reflexão para reduzir a sensibilidade ao arrasto assim:
Funciona como um encanto para mim.
fonte
Existe um problema com a solução de nhasan:
Se o deslize horizontal que aciona a
setEnabled(false)
chamada noSwipeRefreshLayout
noOnPageChangeListener
acontece quando oSwipeRefreshLayout
já reconheceu um Pull-to-Reload, mas ainda não chamou o retorno de chamada de notificação, a animação desaparece, mas o estado interno doSwipeRefreshLayout
permanece em "atualizando" para sempre como não retornos de chamada de notificação são chamados para redefinir o estado. Da perspectiva do usuário, isso significa que Pull-to-Reload não está mais funcionando, pois todos os gestos de pull não são reconhecidos.O problema aqui é que a
disable(false)
chamada remove a animação do botão giratório e o retorno de chamada de notificação é chamado doonAnimationEnd
método de um AnimationListener interno para esse botão giratório que está configurado fora de ordem dessa maneira.Admitimos que nosso testador com os dedos mais rápidos provocou essa situação, mas também pode acontecer de vez em quando em cenários realistas.
Uma solução para corrigir isso é substituir o
onInterceptTouchEvent
método daSwipeRefreshLayout
seguinte maneira:Use
MySwipeRefreshLayout
em seu Layout - Arquivo e altere o código na solução de mhasan parafonte
Pode haver um problema com a resposta @huu duy quando o ViewPager é colocado em um contêiner rolável verticalmente que, por sua vez, é colocado no SwiprRefreshLayout. Se o contêiner rolável de conteúdo não estiver totalmente rolado para cima, então pode não ser possível ative deslizar para atualizar no mesmo gesto de rolar para cima. Na verdade, quando você começa a rolar o contêiner interno e move o dedo horizontalmente mais do que mTouchSlop involuntariamente (que é 8dp por padrão), o CustomSwipeToRefresh proposto recusa esse gesto. Portanto, o usuário deve tentar mais uma vez para iniciar a atualização. Isso pode parecer estranho para o usuário. Extraí o código-fonte do SwipeRefreshLayout original da biblioteca de suporte para meu projeto e reescrevi o onInterceptTouchEvent ().
Veja meu projeto de exemplo no Github .
fonte