English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Implementation de ScrollView Android pour agrandissement de l'image en haut du viewport

préambule

Lors de la réalisation du projet précédent, il fallait réaliser un effet de ScrollView similaire à la page personnelle de Weibo, c'est-à-dire que lorsque vous atteignez le sommet, vous pouvez continuer à tirer vers le bas pour agrandir l'image du sommet. Ensuite, j'ai trouvé un article pertinent en ligne, l'effet est très bon, et le code est également simple et facile à comprendre. (Lien : Custom scrollView pour réaliser l'effet de l'image du sommet qui s'agrandit en tirant vers le bas). Alors, ici, je n'ai fait que quelques modifications sur cette base, par exemple, contrôler le centrage de l'image dans le code, ajouter la capacité de définir dynamiquement le contrôle à agrandir, utiliser le facteur d'agrandissement maximal personnalisé, etc., ce sont des modifications très simples, et j'ai également ajouté l'appel de retour de surveillance du glissement (nécessité du projet).

l'effet est le suivant :

logique

comme toujours, parlons d'abord de la logique, car la logique est la plus importante. Les étapes spécifiques sont les suivantes :
1. Obtenir le contrôle à agrandir et obtenir ses dimensions;
2. Continuer à tirer vers le bas en haut, modifier la largeur et la hauteur du contrôle via LayoutParams;
3. Lorsque le doigt est levé, initialiser les paramètres de divers éléments, faire rebondir le contrôle via l'animation des propriétés.

implémentation

regardez directement le code

public class HeadZoomScrollView extends ScrollView {
 public HeadZoomScrollView(Context context) {
  super(context);
 }
 public HeadZoomScrollView(Context context, AttributeSet attrs) {
  super(context, attrs);
 }
 public HeadZoomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
 }
 // utilisé pour enregistrer la position du défilement
 private float y = 0f;
 // largeur et hauteur d'origine de zoomView
 private int zoomViewWidth = 0;
 private int zoomViewHeight = 0;
 // Est-ce que le zoom est en cours
 private boolean mScaling = false;
 // View agrandie, par défaut le premier sous-view
 private View zoomView;
 public void setZoomView(View zoomView) {
  this.zoomView = zoomView;
 }
 // Coefficient de zoom glissant, plus le coefficient est grand, plus le zoom glissant est important
 private float mScaleRatio = 0.4f;
 public void setmScaleRatio(float mScaleRatio) {
  this.mScaleRatio = mScaleRatio;
 }
 // Le facteur de zoom maximum
 private float mScaleTimes = 2f;
 public void setmScaleTimes(int mScaleTimes) {
  this.mScaleTimes = mScaleTimes;
 }
 // Coefficient de temps de rebond, plus le coefficient est petit, plus le rebond est rapide
 private float mReplyRatio = 0.5f;
 public void setmReplyRatio(float mReplyRatio) {
  this.mReplyRatio = mReplyRatio;
 }
 @Override
 protected void onFinishInflate() {
  super.onFinishInflate();
//  Ne pas permettre un défilement en excès, sinon après un défilement vers le haut, un défilement vers le bas peut apparaître avec une partie vide
  setOverScrollMode(OVER_SCROLL_NEVER);
//  Obtenir le premier view par défaut
  if (getChildAt(0) != null && getChildAt(0) instanceof ViewGroup && zoomView == null) {
   ViewGroup vg = (ViewGroup) getChildAt(0);
   if (vg.getChildCount() > 0) {
    zoomView = vg.getChildAt(0);
   }
  }
 }
 @Override
 public boolean onTouchEvent(MotionEvent ev) {
  if (zoomViewWidth <= 0 || zoomViewHeight <= 0) {
   zoomViewWidth = zoomView.getMeasuredWidth();
   zoomViewHeight = zoomView.getMeasuredHeight();
  }
  if (zoomView == null || zoomViewWidth <= 0 || zoomViewHeight <= 0) {
   return super.onTouchEvent(ev);
  }
  switch (ev.getAction()) {
   case MotionEvent.ACTION_MOVE:
    if (!mScaling) {
     if (getScrollY() == 0) {
      y = ev.getY();//enregistrer la position lors du défilement vers le haut
     } else {
      break;
     }
    }
    int distance = (int) ((ev.getY() - y)*mScaleRatio);
    if (distance < 0) break;//si le défilement est vers le bas
    mScaling = true;
    setZoom(distance);
    return true;
   case MotionEvent.ACTION_UP:
    mScaling = false;
    replyView();
    break;
  }
  return super.onTouchEvent(ev);
 }
 /**agrandir la vue*/
 private void setZoom(float s) {
  float scaleTimes = (float) ((zoomViewWidth+s)/(zoomViewWidth*1.0));
//  si la zoom est supérieure au facteur maximal de zoom, retourner directement
  if (scaleTimes > mScaleTimes) return;
  ViewGroup.LayoutParams layoutParams = zoomView.getLayoutParams();
  layoutParams.width = (int) (zoomViewWidth + s);
  layoutParams.height = (int)(zoomViewHeight*((zoomViewWidth+s)/);
//  centrer horizontalement le contrôle
  ((MarginLayoutParams) layoutParams).setMargins(-(layoutParams.width) - zoomViewWidth) / 2, 0, 0, 0);
  zoomView.setLayoutParams(layoutParams);
 }
 /**rebond*/
 private void replyView() {
  final float distance = zoomView.getMeasuredWidth() - zoomViewWidth;
  // 设置动画
  ValueAnimator anim = ObjectAnimator.ofFloat(distance, 0.0F).setDuration((long) (distance * mReplyRatio));
  anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
   @Override
   public void onAnimationUpdate(ValueAnimator animation) {
    setZoom((Float) animation.getAnimatedValue());
   }
  });
  anim.start();
 }
 @Override
 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
  super.onScrollChanged(l, t, oldl, oldt);
  if (onScrollListener!=null) onScrollListener.onScroll(l, t, oldl, oldt);
 }
 private OnScrollListener onScrollListener;
 public void setOnScrollListener(OnScrollListener onScrollListener) {
  this.onScrollListener = onScrollListener;
 }
 /**écouteur de défilement*/
 public interface OnScrollListener{
  void onScroll(int scrollX, int scrollY, int oldScrollX, int oldScrollY);
 }
}

Vous pouvez voir que dans la méthode onTouchEvent, d'abord jugez si l'état actuel est agrandi, si ce n'est pas le cas, enregistrez la position de l'événement de touche en haut, bien sûr, cela peut également être écrit dans l'événement ACTION_DOWN, si ce n'est pas en haut, ne traitez pas.

Ensuite, calculez la distance glissée, si vous glissez vers le bas, ne traitez pas, notez que cette distance fait référence à la distance entre la position actuelle et l'ACTION_DOWN initiale, donc lorsque cette distance est inférieure à 0, c'est 'pas agrandi && glisser vers le bas'. Dans ce cas, c'est le ScrollView qui doit être glissé. Eh bien, ce n'est pas mal. Lorsque la distance n'est pas inférieure à 0, commencez à agrandir le contrôle, vous pouvez voir que la méthode setZoom est appelée. Notez que, dans ce cas, le contrôle de glissement et d'agrandissement, et le rétablissement de l'agrandissement sont tous faits. Le rebond est également appelé cette méthode.

Rebondir lorsque vous relâchez, ce n'est pas nécessaire de dire.

En termes de code, cela est assez simple, si vous avez besoin d'autres implémentations, cela peut également être ajouté très facilement, par exemple, lorsque nous devons agrandir une image comme Weibo, tourner la fleur d'oranger externe, puis rafraîchir les données lorsque vous relâchez, vous pouvez
Ajoutez l'interface de rappel dans onTouchEvent, puis implémentez la logique spécifique à l'extérieur.

Utilisation

Vous pouvez l'utiliser directement comme un ScollView ordinaire, cela ne nécessite pas d'explications supplémentaires.

Code source :Adresse de téléchargement

Voici la fin de cet article, j'espère qu'il vous sera utile dans vos études, et j'espère que vous soutenirez également le tutoriel d'alarme.

Déclaration : Le contenu de cet article est issu du réseau, la propriété intellectuelle appartient à ses auteurs respectifs, le contenu est apporté par les utilisateurs d'Internet de manière spontanée et est téléversé directement. Ce site n'est pas propriétaire des droits d'auteur, n'a pas été traité par l'éditeur humain et n'assume aucune responsabilité juridique. Si vous trouvez du contenu présumé violer les droits d'auteur, veuillez envoyer un e-mail à : notice#w3Adresse de téléchargement : (Lorsque vous envoyez un e-mail, veuillez remplacer # par @ pour signaler un abus, et fournissez des preuves pertinentes. Une fois confirmé, ce site supprimera immédiatement le contenu présumé enfreindre les droits d'auteur.)

Vous pourriez aussi aimer