J'essaie d'ajouter la même fonctionnalité que celle montrée sur de nombreuses applications, où la zone supérieure de l'écran se rétrécit et se développe en fonction du contenu défilé.
Pour cela, j'utilise la bibliothèque de conception de Google, comme indiqué sur l'exemple CheeseSquare .
La chose est, peu importe la quantité de contenu dans NestedScrollView, cela me permet de faire défiler bien en dessous de la dernière vue du contenu, juste pour me permettre de voir l'état final de la barre d'action, ayant la taille minimale de lui-même.
En bref, voici ce que je vois en faisant défiler vers le bas (contenu modifié de l'exemple CheeseSquare):
alors que c'est ce que j'aimerais avoir en faisant défiler vers le bas (extrait de l'application contacts):
J'essaie également de corriger un bogue sur ThreePhasesBottomSheet échantillon que le défilement dans le contenu de la feuille inférieure est possible même lorsqu'il est en coup d'œil. Pour reproduire, commencez à faire défiler horizontalement (ce qui ne fait rien, car il n'y a rien à faire défiler de cette façon) puis verticalement, ce qui déclencherait en quelque sorte le défilement du contenu de la feuille inférieure.
Par conséquent, je dois y désactiver le défilement dans la méthode "transformView ()", dans le cas où "traduction
Voici comment cela fonctionne en utilisant une utilisation normale:
Et voici comment il se comporte avec le bug de ne pas bloquer le défilement:
J'ai essayé de jouer avec les drapeaux " layout_scrollFlags ", pour changer la hauteur en wrap_content et pour supprimer le clipToPadding et les attributs fitSystemWindows.
Voici l'exemple de fichier XML, que j'ai modifié pour n'inclure qu'un seul cardView au lieu de plusieurs:
<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:fitsSystemWindows="true">
<Android.support.design.widget.AppBarLayout
Android:id="@+id/appbar"
Android:layout_width="match_parent"
Android:layout_height="@dimen/detail_backdrop_height"
Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
Android:fitsSystemWindows="true">
<Android.support.design.widget.CollapsingToolbarLayout
Android:id="@+id/collapsing_toolbar"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
Android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp">
<ImageView
Android:id="@+id/backdrop"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:scaleType="centerCrop"
Android:fitsSystemWindows="true"
app:layout_collapseMode="parallax" />
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin" />
</Android.support.design.widget.CollapsingToolbarLayout>
</Android.support.design.widget.AppBarLayout>
<Android.support.v4.widget.NestedScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical"
Android:paddingTop="24dp">
<Android.support.v7.widget.CardView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_margin="@dimen/card_margin">
<LinearLayout
style="@style/Widget.CardContent"
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="Info"
Android:textAppearance="@style/TextAppearance.AppCompat.Title" />
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="@string/cheese_ipsum" />
</LinearLayout>
</Android.support.v7.widget.CardView>
</LinearLayout>
</Android.support.v4.widget.NestedScrollView>
<Android.support.design.widget.FloatingActionButton
Android:layout_height="wrap_content"
Android:layout_width="wrap_content"
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"
Android:src="@drawable/ic_discuss"
Android:layout_margin="@dimen/fab_margin"
Android:clickable="true"/>
</Android.support.design.widget.CoordinatorLayout>
J'ai aussi essayé le code suivant:
((AppBarLayout.LayoutParams) collapsingToolbar.getLayoutParams()).setScrollFlags(0);
mais cela permettait toujours le défilement du NestedScrollView lui-même dans l'exemple CheeseSquare , et permettait également de lancer le ( ThreePhasesBottomSheet échantillon.
Que puis-je faire pour arrêter le défilement lorsqu'il n'y a plus de contenu à afficher en bas?
De plus, que peut-on faire pour désactiver le défilement de NestedScrollView à tout moment (pour l'exemple ThreePhasesBottomSheet )? Quelque chose comme "setEnableScrolling (...)"?
J'ai essayé d'étendre NestedScrollView et également à partir de ScrollingViewBehavior, mais je n'ai pas trouvé ce qui peut être fait pour désactiver le défilement.
C'est probablement une chose très simple à changer, mais je ne sais pas quoi ...
EDIT: si nécessaire, c'est ce que j'utilise actuellement pour la bibliothèque de conception et de support
compile 'com.Android.support:appcompat-v7:23.1.0'
compile 'com.Android.support:design:23.1.0'
EDIT: pour # 2, j'ai trouvé une solution de contournement dans le fichier BottomSheetLayout.Java, pour désactiver tout ce qui est lié à la variable "sheetViewOwnsTouch", comme si elle était toujours définie sur "false". Cela permettra de voler des événements tactiles sur la feuille inférieure. Cependant, ce n'est qu'une solution de contournement, et uniquement pour ce cas. Cela provoque également certains événements tactiles qui auraient dû être gérés par d'autres vues. Je souhaite toujours savoir comment bloquer le défilement par programme, et aussi dans l'autre cas de suffisamment d'espace pour afficher le contenu.
Que puis-je faire pour arrêter le défilement lorsqu'il n'y a pas plus de contenu à afficher en bas?
Tout d'abord, comme je l'ai commenté ci-dessous, le défilement que vous avez dit dans votre question n'est pas du NestedScrollView
. Il appartient au CollapsingToolbarLayout
. L'événement de défilement de NestedScrollView
ne se produit que lorsque CollapsingToolbarLayout
est complètement réduit, et bien sûr il arrêtera de défiler lorsqu'il n'y aura plus de contenu à l'intérieur (en bas atteint). Pour le CollapsingToolbarLayout
, il se réduira à la disposition_hauteur de sa barre d'outils (comme dans le fichier xml, vous trouverez "?attr/actionBarSize"
). L'image suivante montrera que, faites attention au rectangle rouge qui est la barre d'outils (j'ai défini son arrière-plan)
Donc, pour avoir une solution pour votre # 1, vous devez calculer la hauteur de NestedScrollView
, puis si elle est plus petite que la hauteur de l'écran, nous fixons la hauteur de la barre d'outils.
En bref, vous pouvez mettre à jour activity_detail.xml
comme suit:
<?xml version="1.0" encoding="utf-8"?>
<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:fitsSystemWindows="true">
<Android.support.design.widget.AppBarLayout
Android:id="@+id/appbar"
Android:layout_width="match_parent"
Android:layout_height="@dimen/detail_backdrop_height"
Android:fitsSystemWindows="true"
Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<Android.support.design.widget.CollapsingToolbarLayout
Android:id="@+id/collapsing_toolbar"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
Android:id="@+id/backdrop"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="false"
Android:scaleType="centerCrop"
app:layout_collapseMode="parallax" />
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</Android.support.design.widget.CollapsingToolbarLayout>
</Android.support.design.widget.AppBarLayout>
<Android.support.v4.widget.NestedScrollView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
Android:id="@+id/linearLayout1"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<Android.support.v7.widget.CardView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_margin="@dimen/card_margin">
<LinearLayout
style="@style/Widget.CardContent"
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="Info"
Android:textAppearance="@style/TextAppearance.AppCompat.Title" />
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="@string/cheese_ipsum" />
</LinearLayout>
</Android.support.v7.widget.CardView>
</LinearLayout>
</Android.support.v4.widget.NestedScrollView>
</Android.support.design.widget.CoordinatorLayout>
Et CheeseDetailActivity.Java:
public class CheeseDetailActivity extends AppCompatActivity {
public static final String EXTRA_NAME = "cheese_name";
private final Context mContext = this;
private int screenHeight;
private int linearLayoutHeight;
private int toolbarHeight_org;
private int toolbarHeight;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
Intent intent = getIntent();
final String cheeseName = intent.getStringExtra(EXTRA_NAME);
screenHeight = getScreenHeight(this);
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true);
final int colorPrimary = typedValue.data;
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
AppBarLayout appbar = (AppBarLayout) findViewById(R.id.appbar);
final CoordinatorLayout.LayoutParams appbarLayoutParams = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
final ViewGroup.LayoutParams toolbarLayoutParams = toolbar.getLayoutParams();
if (toolbarLayoutParams != null) {
toolbarHeight_org = toolbarLayoutParams.height;
toolbarHeight = toolbarLayoutParams.height;
}
final CollapsingToolbarLayout collapsingToolbar =
(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle(cheeseName);
collapsingToolbar.setContentScrimColor(colorPrimary);
collapsingToolbar.setExpandedTitleTextAppearance(R.style.ExpandedTitleTextAppearance);
//collapsingToolbar.setCollapsedTitleTextAppearance(R.style.CollapsedTitleTextAppearance);
final LinearLayout linearLayout = (LinearLayout) findViewById(R.id.linearLayout1);
ViewTreeObserver observer = linearLayout.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
linearLayoutHeight = linearLayout.getHeight();
if (linearLayoutHeight + toolbarHeight < screenHeight) {
if (toolbarLayoutParams != null) {
toolbarLayoutParams.height = screenHeight - linearLayoutHeight - 20;
if (toolbarLayoutParams.height < toolbarHeight_org) {
toolbarLayoutParams.height = toolbarHeight_org;
}
int extended_text_size = (int) getResources().getDimension(R.dimen.expanded_text_size);
if (appbarLayoutParams.height - toolbarLayoutParams.height <= extended_text_size) {
int value = appbarLayoutParams.height - toolbarLayoutParams.height;
if (value < 0) {
appbarLayoutParams.height = toolbarLayoutParams.height - value + extended_text_size * 3;
} else {
appbarLayoutParams.height = toolbarLayoutParams.height + extended_text_size * 3;
}
if (appbarLayoutParams.height >= screenHeight) {
appbarLayoutParams.height = screenHeight;
}
}
// collapsingToolbar.setContentScrimColor(getResources().getColor(Android.R.color.transparent));
if (toolbarLayoutParams.height > toolbarHeight_org) {
collapsingToolbar.setContentScrimColor(ContextCompat.getColor(mContext, Android.R.color.transparent));
}
}
}
// Removes the listener if possible
ViewTreeObserver viewTreeObserver = linearLayout.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
linearLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
}
});
loadBackdrop();
appbar.setExpanded(true);
}
private int getScreenHeight(Context context) {
int measuredHeight;
Point size = new Point();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
wm.getDefaultDisplay().getSize(size);
measuredHeight = size.y;
} else {
Display d = wm.getDefaultDisplay();
measuredHeight = d.getHeight();
}
return measuredHeight;
}
private void loadBackdrop() {
final ImageView imageView = (ImageView) findViewById(R.id.backdrop);
Glide.with(this).load(Cheeses.getRandomCheeseDrawable()).centerCrop().into(imageView);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.sample_actions, menu);
return true;
}
}
Voici le résultat:
Avec l'échantillon Cheesesquare , j'ai personnalisé ce projet et téléchargé sur My GitHub . Je suis d'accord qu'il a encore quelques problèmes, cependant, au moins cela peut être une solution pour votre 1er problème.
S'il vous plaît, jetez un oeil. J'espère que ça aide!
Pour désactiver le défilement, définissez simplement NestedScrollView et sa hauteur enfant LinearLayout sur 'wrap_content'.
Cela ne fonctionnera pas complètement comme vous le souhaitez, mais au moins il ne pourra pas défiler, si le contenu tient complètement à l'écran.
En parlant de votre exemple d'application Contacts, il semble qu'il n'utilise pas CoordinatorLayout et d'autres éléments qui l'accompagnent.
Ce comportement peut être fait de cette manière:
<ScrollView
Android:id="@+id/scroll_adinfo"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<FrameLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical">
<ImageView
Android:id="@+id/image"
Android:layout_width="match_parent"
Android:layout_height="@dimen/image_height"
Android:src="@mipmap/ic_launcher"/>
<LinearLayout
Android:id="@+id/layout_content"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:paddingTop="@dimen/image_height">
<!-- YOUR CONTENT HERE -->
</LinearLayout>
</FrameLayout>
</ScrollView>
Et dans votre code vous allez déplacer l'image sur défilement:
final ImageView image = (ImageView) findViewById(R.id.image);
((ScrollView) rootView.findViewById(R.id.scroll_adinfo)).getViewTreeObserver().addOnScrollChangedListener(
new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
int scrollY = ((ScrollView) rootView.findViewById(R.id.scroll_adinfo)).getScrollY();
image.setY(scrollY / 2);
}
});
J'ai extrait cela d'un de mes projets et l'ai édité pour que je puisse rater quelque chose.