Освой программирование играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

ImageSwitcher

Базовый пример
Анимация затемнения
Динамическая смена картинок
Управление жестами
Слайд-шоу

Компонент ImageSwitcher наследуется от класса ViewSwitcher и позволяет заменять текущий элемент View на другой элемент View. Самый распространённый вариант - использование ImageView. Одновременно на экране может отображаться только один элемент View. Во время перехода между элементами View могут использоваться анимации (плавные появления/исчезновения и вращения). В студии находится в разделе Expert.

Базовый пример

Дочерние элементы View создаются при помощи экземпляра класса ViewFactory. Например, элемент ImageSwitcher и его соответствующий экземпляр класса ViewFactory могут быть использованы для генерации элемента ImageView текущего вопроса викторины и для последующего переключения на элемент ImageView следующего вопроса, когда пользователь щёлкнет по кнопке Вперёд или Назад.

Создадим новый проект и добавим элементы в разметку.


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ImageSwitcher
        android:id="@+id/imageSwitcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:onClick="onSwitcherClick">

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/cat_cage"/>

        <ImageView
            android:id="@+id/imageView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/cat_tied"/>
    </ImageSwitcher>

</LinearLayout>

Обратите внимание, что элементы ImageView являются дочерними и вложены в ImageSwitcher. Также у атрибута onClick задан обработчик onSwitcherClick. Осталось написать код:


package ru.alexanderklimov.imageswitcherdemo;

import ...

public class MainActivity extends Activity {
	
	private ImageSwitcher mImageSwitcher;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		mImageSwitcher = (ImageSwitcher)findViewById(R.id.imageSwitcher);
	}
	
	public void onSwitcherClick(View view){
		mImageSwitcher.showNext();
	}
}

Метод showNext() выводит следующий элемент. Вывод происходит циклически в одном направлении. Если у вас используются две картинки, то они будут по очереди сменять друг друга. Для смены изображения в обратную сторону используется метод showPrevious().

Анимация затемнения

Мы рассмотрели простейший пример смены одного изображения на другое. Причём, смена происходит сразу, без задержки. Чтобы смена изображений происходила красиво, нужно подключить анимацию.


mImageSwitcher = (ImageSwitcher)findViewById(R.id.imageSwitcher);
Animation inAnimation = new AlphaAnimation(0, 1);
inAnimation.setDuration(2000);
Animation outAnimation = new AlphaAnimation(1, 0);
outAnimation.setDuration(2000);

mImageSwitcher.setInAnimation(inAnimation);
mImageSwitcher.setOutAnimation(outAnimation);

Добавив код к предыдущему примеру, вы получите плавную анимацию с использованием прозрачности. Первая картинка будет плавно исчезать, уступая второму изображению.

Динамическая смена картинок

Рассмотрим более продвинутый пример. Подготовьте несколько картинок в папке res/drawable. На экран активности добавим две кнопки для просмотра картинок Вперёд и Назад. На этот раз мы уже не используем дочерние элементы ImageView. Картинки будут загружаться динамически.


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/buttonPrev"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:text="&lt;&lt;"/>

        <Button
            android:id="@+id/buttonForward"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:text=">>"/>
    </LinearLayout>

    <ImageSwitcher
        android:id="@+id/imageSwitcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal">

    </ImageSwitcher>

</LinearLayout>

Напишем код для управления галереей.


package ru.alexanderklimov.imageswitcherdemo;

import ...


public class MainActivity extends AppCompatActivity  implements ViewSwitcher.ViewFactory {

    private ImageSwitcher mImageSwitcher;
    int position = 0;
    private int[] mImageIds = { R.drawable.cat1, R.drawable.cat2,
            R.drawable.cat3, R.drawable.cat4, R.drawable.cat5,
            R.drawable.cat6, R.drawable.cat7, };

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

        setContentView(R.layout.activity_main);

        mImageSwitcher = (ImageSwitcher)findViewById(R.id.imageSwitcher);
        mImageSwitcher.setFactory(this);

        Animation inAnimation = new AlphaAnimation(0, 1);
        inAnimation.setDuration(2000);
        Animation outAnimation = new AlphaAnimation(1, 0);
        outAnimation.setDuration(2000);

        mImageSwitcher.setInAnimation(inAnimation);
        mImageSwitcher.setOutAnimation(outAnimation);

        mImageSwitcher.setImageResource(mImageIds[0]);
    }

    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.buttonForward:
                setPositionNext();
                mImageSwitcher.setImageResource(mImageIds[position]);
                break;
            case R.id.buttonPrev:
                setPositionPrev();
                mImageSwitcher.setImageResource(mImageIds[position]);
                break;

            default:
                break;
        }
    }

    public void setPositionNext() {
        position++;
        if (position > mImageIds.length - 1) {
            position = 0;
        }
    }

    public void setPositionPrev() {
        position--;
        if (position < 0) {
            position = mImageIds.length - 1;
        }
    }

    @Override
    public View makeView() {
        ImageView imageView = new ImageView(this);
        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imageView.setLayoutParams(new
                ImageSwitcher.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
        imageView.setBackgroundColor(0xFF000000);
        return imageView;
    }
}

Вначале мы прописали массив графических ресурсов, а также определили переменную position для определения текущей позиции.

Далее кроме знакомых нам методов для анимации, вызываем методы setFactory() и setImageResource().

Метод setFactory() помогает указать подходящий класс ViewFactory, позволяющий менять изображения по очереди. Класс ViewFactory имеет всего один обязательный метод — метод makeView(). Этот метод должен возвращать View подходящего типа, в нашем примере определённым образом настроенный элемент ImageView.

Метод setImageResource() загружает изображение из ресурсов.

Вспомогательные методы setPositionNext() и setPositionPrev() позволяют установить значение для текущей позиции, которое используется в обработчиках нажатий кнопок.

Управление жестами

Если вы хотите управлять сменой картинок не через кнопки Вперёд/Назад, а движением пальца, то нужно подключить класс GestureDetector. Дополним предыдущий пример.


package ru.alexanderklimov.imageswitcherdemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ViewSwitcher;


public class MainActivity extends AppCompatActivity  implements ViewSwitcher.ViewFactory, GestureDetector.OnGestureListener {

    private ImageSwitcher mImageSwitcher;
    int position = 0;
    private int[] mImageIds = { R.drawable.cat1, R.drawable.cat2,
            R.drawable.cat3, R.drawable.cat4, R.drawable.cat5,
            R.drawable.cat6, R.drawable.cat7, };

    private GestureDetector mGestureDetector;
    private static final int SWIPE_MIN_DISTANCE = 120;
    private static final int SWIPE_MAX_OFF_PATH = 250;
    private static final int SWIPE_THRESHOLD_VELOCITY = 100;

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

        setContentView(R.layout.activity_main);

        mImageSwitcher = (ImageSwitcher)findViewById(R.id.imageSwitcher);
        mImageSwitcher.setFactory(this);

        Animation inAnimation = new AlphaAnimation(0, 1);
        inAnimation.setDuration(2000);
        Animation outAnimation = new AlphaAnimation(1, 0);
        outAnimation.setDuration(2000);

        mImageSwitcher.setInAnimation(inAnimation);
        mImageSwitcher.setOutAnimation(outAnimation);

        mImageSwitcher.setImageResource(mImageIds[0]);

        mGestureDetector = new GestureDetector(this, this);

    }

    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.buttonForward:
                setPositionNext();
                mImageSwitcher.setImageResource(mImageIds[position]);
                break;
            case R.id.buttonPrev:
                setPositionPrev();
                mImageSwitcher.setImageResource(mImageIds[position]);
                break;

            default:
                break;
        }
    }

    public void setPositionNext() {
        position++;
        if (position > mImageIds.length - 1) {
            position = 0;
        }
    }

    public void setPositionPrev() {
        position--;
        if (position < 0) {
            position = mImageIds.length - 1;
        }
    }

    @Override
    public View makeView() {
        ImageView imageView = new ImageView(this);
        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imageView.setLayoutParams(new
                ImageSwitcher.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
        imageView.setBackgroundColor(0xFF000000);
        return imageView;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        try {
            if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
                return false;
            // справа налево
            if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                setPositionNext();
                mImageSwitcher.setImageResource(mImageIds[position]);
            } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                // слева направо
                setPositionPrev();
                mImageSwitcher.setImageResource(mImageIds[position]);
            }
        } catch (Exception e) {
            // nothing
            return true;
        }
        return true;
    }
}

ImageSwitcher

Слайд-шоу

По такому же принципу можно устроить анимацию в виде слайд-шоу.


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              android:paddingBottom="@dimen/activity_vertical_margin"
              android:paddingLeft="@dimen/activity_horizontal_margin"
              android:paddingRight="@dimen/activity_horizontal_margin"
              android:paddingTop="@dimen/activity_vertical_margin"
              tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Далее"/>

    <ImageSwitcher
        android:id="@+id/imageSwitcher"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

</LinearLayout>

Код. Не забудьте подготовить несколько картинок в ресурсах.


package ru.alexanderklimov.imageswitcherdemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ViewSwitcher;


public class MainActivity extends AppCompatActivity {

    private ImageSwitcher mImageSwitcher;

    // массив картинок
    private int[] mImageIds = {R.drawable.cat1, R.drawable.cat2, R.drawable.cat3,
            R.drawable.cat4, R.drawable.cat5};

    private int mCurIndex;

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

        setContentView(R.layout.activity_main);

        mImageSwitcher = (ImageSwitcher) findViewById(R.id.imageSwitcher);

        Animation slideInLeftAnimation = AnimationUtils.loadAnimation(this,
                android.R.anim.slide_in_left);
        Animation slideOutRight = AnimationUtils.loadAnimation(this,
                android.R.anim.slide_out_right);

        mImageSwitcher.setInAnimation(slideInLeftAnimation);
        mImageSwitcher.setOutAnimation(slideOutRight);

        mImageSwitcher.setFactory(new ViewSwitcher.ViewFactory() {

            @Override
            public View makeView() {

                ImageView imageView = new ImageView(MainActivity.this);
                imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);

                LayoutParams params = new ImageSwitcher.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);

                imageView.setLayoutParams(params);
                return imageView;
            }
        });

        mCurIndex = 0;
        mImageSwitcher.setImageResource(mImageIds[mCurIndex]);
    }

    public void onClick(View v) {
        if (mCurIndex == mImageIds.length - 1) {
            mCurIndex = 0;
            mImageSwitcher.setImageResource(mImageIds[mCurIndex]);
        } else {
            mImageSwitcher.setImageResource(mImageIds[++mCurIndex]);
        }
    }
}
Реклама