web-dev-qa-db-fra.com

Android: faire défiler une vue d'image

J'ai une ImageView qui fait deux fois la hauteur d'un écran normal (960 dip). Je voudrais le faire défiler de haut en bas sur l'écran. Le bas de l'écran doit contenir un bouton. J'ai essayé différentes combinaisons de ScrollView et d'Imageviews sans succès. J'ai également réfléchi à l'attribut: isScrollContainer sans résultats. Est-ce que quelqu'un sait comment faire cela? À la vôtre, Luca

24
luca

@ cV2 Merci beaucoup pour ce code. Cela m'a permis d'aller dans la direction dont j'avais besoin. Voici ma version modifiée qui arrête de défiler sur les bords de l'image ...

    // set maximum scroll amount (based on center of image)
    int maxX = (int)((bitmapWidth / 2) - (screenWidth / 2));
    int maxY = (int)((bitmapHeight / 2) - (screenHeight / 2));

    // set scroll limits
    final int maxLeft = (maxX * -1);
    final int maxRight = maxX;
    final int maxTop = (maxY * -1);
    final int maxBottom = maxY;

    // set touchlistener
    ImageView_BitmapView.setOnTouchListener(new View.OnTouchListener()
    {
        float downX, downY;
        int totalX, totalY;
        int scrollByX, scrollByY;
        public boolean onTouch(View view, MotionEvent event)
        {
            float currentX, currentY;
            switch (event.getAction())
            {
                case MotionEvent.ACTION_DOWN:
                    downX = event.getX();
                    downY = event.getY();
                    break;

                case MotionEvent.ACTION_MOVE:
                    currentX = event.getX();
                    currentY = event.getY();
                    scrollByX = (int)(downX - currentX);
                    scrollByY = (int)(downY - currentY);

                    // scrolling to left side of image (pic moving to the right)
                    if (currentX > downX)
                    {
                        if (totalX == maxLeft)
                        {
                            scrollByX = 0;
                        }
                        if (totalX > maxLeft)
                        {
                            totalX = totalX + scrollByX;
                        }
                        if (totalX < maxLeft)
                        {
                            scrollByX = maxLeft - (totalX - scrollByX);
                            totalX = maxLeft;
                        }
                    }

                    // scrolling to right side of image (pic moving to the left)
                    if (currentX < downX)
                    {
                        if (totalX == maxRight)
                        {
                            scrollByX = 0;
                        }
                        if (totalX < maxRight)
                        {
                            totalX = totalX + scrollByX;
                        }
                        if (totalX > maxRight)
                        {
                            scrollByX = maxRight - (totalX - scrollByX);
                            totalX = maxRight;
                        }
                    }

                    // scrolling to top of image (pic moving to the bottom)
                    if (currentY > downY)
                    {
                        if (totalY == maxTop)
                        {
                            scrollByY = 0;
                        }
                        if (totalY > maxTop)
                        {
                            totalY = totalY + scrollByY;
                        }
                        if (totalY < maxTop)
                        {
                            scrollByY = maxTop - (totalY - scrollByY);
                            totalY = maxTop;
                        }
                    }

                    // scrolling to bottom of image (pic moving to the top)
                    if (currentY < downY)
                    {
                        if (totalY == maxBottom)
                        {
                            scrollByY = 0;
                        }
                        if (totalY < maxBottom)
                        {
                            totalY = totalY + scrollByY;
                        }
                        if (totalY > maxBottom)
                        {
                            scrollByY = maxBottom - (totalY - scrollByY);
                            totalY = maxBottom;
                        }
                    }

                    ImageView_BitmapView.scrollBy(scrollByX, scrollByY);
                    downX = currentX;
                    downY = currentY;
                    break;

            }

            return true;
        }
    });

Je suis sûr que cela pourrait être un peu raffiné, mais cela fonctionne plutôt bien. :)

33
wirbly

J'ai cherché si longtemps ce code, donc je voulais partager cette grande paix de code:

ce code provient d'une activité, qui a un fichier xml sur le backend contenant un ImageView appelé 'img'

<ImageView
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:id="@+id/img"
    Android:scaleType="center"
    Android:background="#fff"
    Android:src="@drawable/picName"
/>

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.xml_name_layout);

    final ImageView switcherView = (ImageView) this.findViewById(R.id.img);

    switcherView.setOnTouchListener(new View.OnTouchListener() {

        public boolean onTouch(View arg0, MotionEvent event) {

            float curX, curY;

            switch (event.getAction()) {

                case MotionEvent.ACTION_DOWN:
                    mx = event.getX();
                    my = event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    curX = event.getX();
                    curY = event.getY();
                    switcherView.scrollBy((int) (mx - curX), (int) (my - curY));
                    mx = curX;
                    my = curY;
                    break;
                case MotionEvent.ACTION_UP:
                    curX = event.getX();
                    curY = event.getY();
                    switcherView.scrollBy((int) (mx - curX), (int) (my - curY));
                    break;
            }

            return true;
        }
    });

}

a fait le travail parfaitement pour moi ... défilement vertical horizontal inclus (activé)

le seul côté négatif est ... vous pouvez faire défiler le bord de l'image ... mais ce n'est pas un problème pour moi .. et passer du temps, vous pouvez facilement mettre en œuvre cette fonctionnalité :)

bonne chance, amuse toi bien

28
cV2

voici comment je l'ai corrigé: p

<ScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:scrollbarAlwaysDrawVerticalTrack="true" >

<ImageView
    Android:contentDescription="Specs"
    Android:adjustViewBounds="true"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:scrollbars="vertical"
    Android:src="@drawable/specs" >
</ImageView>
17
frapeti

@wirbly Merci beaucoup pour votre code, il fonctionne exactement comme je le souhaite. Mais quand j'ai lu votre code pour la première fois, j'étais un peu confus au sujet des quatre variables que vous avez oublié de définir.

Donc, je veux ajouter la définition du code pour le rendre plus clair.

Resources res=getResources();
Bitmap mBitmap = BitmapFactory.decodeResource(res, R.drawable.p_1920x1080); 
BitmapDrawable bDrawable = new BitmapDrawable(res, mBitmap);

//get the size of the image and  the screen
int bitmapWidth = bDrawable.getIntrinsicWidth();
int bitmapHeight = bDrawable.getIntrinsicHeight();
int screenWidth = this.getWindowManager().getDefaultDisplay().getWidth();  
int screenHeight = this.getWindowManager().getDefaultDisplay().getHeight();

J'espère que c'est utile.

8
hukeping

La manière la plus simple est à mon humble avis d'utiliser une vue Web et d'y charger l'image via un fichier html local. De cette façon, vous obtiendrez également automatiquement les commandes de zoom si vous souhaitez les utiliser. Pour une grande image (c'est-à-dire si sa largeur est de 1000 ou 3000 px), vous remarquerez que Android (Coliris) n'est pas très bon pour afficher de grandes images zoomées très nettes, même si les images originales sont tranchant et non compressé). C'est un problème connu. La solution pour cela est de décomposer la grande image en petits carreaux et de les recomposer via html (div ou table). J'utilise cette approche pour fournir à l'utilisateur une carte du métro (plus grande que l'écran et pouvant défiler).

    WebView webView = (WebView)findViewById(R.id.webView);
    webView.getSettings().setBuiltInZoomControls(true);
    webView.getSettings().setUseWideViewPort(true);
    webView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);

    webView.loadUrl( "content://com.myapp.Android.localfile/sdcard/myappdata/common/mtr_map.html");

Cela pourrait fonctionner pour la plupart des cas/'applications régulières', bien que cela dépende de votre cas particulier. Si vous parlez d'une image comme arrière-plan défilant d'un jeu, cela pourrait ne pas vous être utile.

Au lieu d'un fichier html, vous pouvez également charger directement l'image (png, jpg). Si vous ne voulez pas la commande de zoom, désactivez-la.

6
Mathias Conradt

Une autre façon consiste à créer un HorizontalScrollView, à y ajouter le imageView, puis à ajouter le HorizontalScrollView dans un ScrollView. Cela vous permet de faites défiler vers le haut, le bas, la gauche, la droite.

2
Mr X

ça marche pour moi

<ScrollView
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:padding="10dp">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical">

        <ImageView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:src="@drawable/img"
            Android:scaleType="centerCrop"
            Android:adjustViewBounds="true"/>

        <Button
            style="@style/btn"
            Android:id="@+id/btn"
            Android:layout_height="60dp"
            Android:layout_marginTop="20dp"
            Android:background="@drawable/btn"
            Android:onClick="click"
            Android:text="text" />
    </LinearLayout>

</ScrollView>
1
Liena

hé les gars ont trouvé une solution facile et fiable à 100% comme Mr X mentionné ci-dessus (car les autres codes mentionnés ne fonctionnaient pas sur certains appareils ou ne fonctionnaient pas) Utilisez simplement ScrollView fourni par Android et cela prend soin des trucs

quelque chose comme ça

<ScrollView Android:layout_width="fill_parent" Android:id="@+id/scrollView1"
        Android:layout_height="wrap_content" Android:layout_alignParentTop="true"
        Android:layout_alignParentLeft="true" Android:layout_above="@+id/button1"
        Android:layout_alignParentRight="true" Android:scrollbarAlwaysDrawVerticalTrack="true">
        <LinearLayout Android:id="@+id/linearLayout1"
            Android:layout_width="fill_parent" Android:layout_height="fill_parent" Android:gravity="center_horizontal">
            <ImageView Android:src="@Android:drawable/ic_menu_report_image"
                Android:layout_height="wrap_content" Android:id="@+id/imageView1"
                Android:layout_width="wrap_content"></ImageView>
        </LinearLayout>
    </ScrollView>

et créer quelque chose comme ça

if (mImageName != null) {
        InputStream is = null;
        try {
            is = this.getResources().getAssets().open("mathematics/"+mImageName);
        } catch (IOException e) {
        }
        Bitmap image = BitmapFactory.decodeStream(is);

        mImageView.setImageBitmap(image);
}

À votre santé!

0
neelabh