Dans mon application, j'ai eu une activité avec une sorte de barre d'actions en haut et la liste en dessous. Ce que je veux faire, c’est faire défiler la liste en haut, pour qu’elle se cache, puis, lorsque la liste est défilée vers le bas, elle devrait défiler avec la liste, comme si elle était juste au-dessus du bord supérieur de l’écran. Comment puis-je obtenir cette fonctionnalité?
Google prend maintenant cela en charge avec la variable CoordinatorLayout
.
<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/main_content"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<Android.support.design.widget.AppBarLayout
Android:id="@+id/appbar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
Android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways" />
<Android.support.design.widget.TabLayout
Android:id="@+id/tabs"
Android:layout_width="match_parent"
Android:layout_height="wrap_content" />
</Android.support.design.widget.AppBarLayout>
<Android.support.v4.view.ViewPager
Android:id="@+id/viewpager"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<Android.support.design.widget.FloatingActionButton
Android:id="@+id/fab"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="end|bottom"
Android:layout_margin="@dimen/fab_margin"
Android:src="@drawable/ic_done" />
</Android.support.design.widget.CoordinatorLayout>
Documenté ici:https://developer.Android.com/reference/Android/support/design/widget/AppBarLayout.html
https://github.com/umano/AndroidSlidingUpPanel
Regardez le code dans ce référentiel. Lorsque vous faites glisser le panneau vers le haut, la barre d’action se glisse également vers le haut.
De la démo:
getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
SlidingUpPanelLayout layout = (SlidingUpPanelLayout) findViewById(R.id.sliding_layout);
layout.setShadowDrawable(getResources().getDrawable(R.drawable.above_shadow));
layout.setAnchorPoint(0.3f);
layout.setPanelSlideListener(new PanelSlideListener() {
@Override
public void onPanelSlide(View panel, float slideOffset) {
Log.i(TAG, "onPanelSlide, offset " + slideOffset);
if (slideOffset < 0.2) {
if (getActionBar().isShowing()) {
getActionBar().hide();
}
} else {
if (!getActionBar().isShowing()) {
getActionBar().show();
}
}
}
@Override
public void onPanelExpanded(View panel) {
Log.i(TAG, "onPanelExpanded");
}
@Override
public void onPanelCollapsed(View panel) {
Log.i(TAG, "onPanelCollapsed");
}
@Override
public void onPanelAnchored(View panel) {
Log.i(TAG, "onPanelAnchored");
}
});
Téléchargez l'exemple ici:
https://play.google.com/store/apps/details?id=com.sothree.umano
Je voulais récemment la même fonctionnalité et cela fonctionne parfaitement pour moi:
Au fur et à mesure que l'utilisateur fait défiler l'écran vers le haut, la barre Action est masquée afin de permettre à l'utilisateur de travailler avec tout l'écran.
Lorsque l'utilisateur fait défiler l'écran vers le bas et s'en va, la barre d'actions reviendra.
getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
listView.setOnScrollListener(new OnScrollListener() {
int mLastFirstVisibleItem = 0;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) { }
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (view.getId() == listView.getId()) {
final int currentFirstVisibleItem = listView.getFirstVisiblePosition();
if (currentFirstVisibleItem > mLastFirstVisibleItem) {
// getSherlockActivity().getSupportActionBar().hide();
getSupportActionBar().hide();
} else if (currentFirstVisibleItem < mLastFirstVisibleItem) {
// getSherlockActivity().getSupportActionBar().show();
getSupportActionBar().show();
}
mLastFirstVisibleItem = currentFirstVisibleItem;
}
}
});
this.mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
int mLastFirstVisibleItem = 0;
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
final int currentFirstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();
if (currentFirstVisibleItem > this.mLastFirstVisibleItem) {
MainActivity.this.getSupportActionBar().hide();
} else if (currentFirstVisibleItem < this.mLastFirstVisibleItem) {
MainActivity.this.getSupportActionBar().show();
}
this.mLastFirstVisibleItem = currentFirstVisibleItem;
}
});
Faites-moi savoir si vous avez besoin de plus d'aide!
Vous constatez le scintillement car en masquant/affichant le ActionBar l’espace disponible pour vos modifications de présentation du contenu, ce qui provoque un relais. Avec cela, l'index de la position du premier élément visible change également (vous pouvez le vérifier en déconnectant mLastFirstVisibleItem et currentFirstVisibleItem.
Vous pouvez faire face au scintillement en laissant la barre d’action recouvrir la présentation de votre contenu. Pour activer le mode superposition pour la barre d'action, vous devez créer un thème personnalisé qui étend un thème de barre d'action existant et définissez la propriété Android: windowActionBarOverlay sur true.
Avec cela, vous pouvez éliminer le scintillement, mais la barre d'action superposera le contenu de votre liste. Une solution simple consiste à définir le remplissage supérieur de la liste (ou de la présentation racine) à la hauteur de la barre d'actions.
<ListView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@Android:id/list"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:paddingTop="?android:attr/actionBarSize" />
Malheureusement, cela se traduira par un remplissage constant au sommet. Un raffinement de cette solution consiste à ajouter une vue en-tête à la vue liste qui a la hauteur de ? Android: attr/actionBarSize (et supprimer le remplissage supérieur défini précédemment).
Ce que vous recherchez s'appelle Modèle de retour rapide , appliqué à la barre d’action. Google IO 2014 app utilise exactement cela. Je l'utilise dans l'une de mes applications. Vous pouvez consulter le code source de cette application Google pour voir comment il l'a obtenu. La classe BaseActivity est l'endroit où vous avez ce dont vous avez besoin, lisez le code et extrayez cette fonctionnalité spécifique. Profitez de la programmation! :)
Je suis sûr que ce n'est pas la meilleure solution. Mais je n'en ai pas encore trouvé de meilleur. J'espère que ça vous sera utile.
static boolean scroll_down;
...
mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (scroll_down) {
actionBar.hide();
} else {
actionBar.show();
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 70) {
//scroll down
scroll_down = true;
} else if (dy < -5) {
//scroll up
scroll_down = false;
}
}
});
Je pense que c'est une bonne idée.
listView.setOnScrollListener(new OnScrollListener() {
int mLastFirstVisibleItem = 0;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case OnScrollListener.SCROLL_STATE_FLING:
if (view.getId()==lv_searchresult_results.getId()){
final int currentFirstVisibleItem=lv_searchresult_results.getFirstVisiblePosition();
if(currentFirstVisibleItem>mLastFirstVisibleItem){
ObjectAnimator.ofFloat(toolbar, "translationY", -toolbar.getHeight()).start();
else if(currentFirstVisibleItem<(mLastFirstVisibleItem)){
ObjectAnimator.ofFloat(toolbar, "translationY", 0).start();
}
mLastFirstVisibleItem= currentFirstVisibleItem;
}
if(lv_searchresult_results.getLastVisiblePosition() == myAdapter.getListMap().size()){
if(myAdapter.getListMap().size() < allRows&&!upLoading){
}
}
break;
case OnScrollListener.SCROLL_STATE_IDLE:
if (view.getFirstVisiblePosition()<=1){
ObjectAnimator.ofFloat(toolbar, "translationY", 0).start();
}
if(lv_searchresult_results.getLastVisiblePosition() == myAdapter.getListMap().size()){
if(myAdapter.getListMap().size() < allRows&&!upLoading){
}
}
break;
Je pense que cela fonctionnera bien .....
listView.setOnScrollListener(new OnScrollListener() {
int mLastFirstVisibleItem = listView.getLastVisiblePosition();
boolean isScrolling = false;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState == 0)
isScrolling = false;
else if(scrollState == 1)
isScrolling = true;
else if(scrollState == 2)
isScrolling = true;
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (view.getId() == myTeamListView.getId()) {
if(isScrolling) {
final int currentFirstVisibleItem = myTeamListView.getLastVisiblePosition();
if (currentFirstVisibleItem > mLastFirstVisibleItem) {
((AppCompatActivity)getActivity()).getSupportActionBar().hide();
} else if (currentFirstVisibleItem < mLastFirstVisibleItem) {
((AppCompatActivity)getActivity()).getSupportActionBar().show();
}
mLastFirstVisibleItem = currentFirstVisibleItem;
}
}
}
});