Эффект складывания листа бумаги

Ответить
antarey
Сообщения: 6
Зарегистрирован: 23 июл 2014, 10:30

Эффект складывания листа бумаги

Сообщение antarey » 23 июл 2014, 11:41

Здравствуйте.
В нете полно примеров реализации данного эффекта к примеру, исходник тут
Но я хочу реализовать этот эффект не через CustomView наследник класса FoldingLayout а через класс Animation

Код: Выделить всё

    Animation anim = new Animation() {

        @Override
        public void initialize(int width, int height, int parentWidth, int parentHeight) {
            super.initialize(width, height, parentWidth, parentHeight);
            mCamera = new Camera();
        }
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {

    по идее тут должен быть код

    };


    anim.setInterpolator(new AccelerateInterpolator());
    anim.setDuration(durationMillis);
    anim.setFillAfter(true);
    view.startAnimation(anim);


}

За основу беру процедуры prepareFold, calculateMatrices и необходимо переделать dispatchDraw чтобы можно было впихнуть в applyTransformation
Вот мой код

Код: Выделить всё

package com.antarey.antnative;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.view.View;
import android.widget.Toast;

/**
 * Created by antarey on 23.07.2014.
 */
public class AntareyAnimation {

    public static enum Orientation {
        VERTICAL,
        HORIZONTAL
    }

    private final float SHADING_ALPHA = 0.8f;
    private final float SHADING_FACTOR = 0.5f;
    private final int DEPTH_CONSTANT = 1500;
    private final int NUM_OF_POLY_POINTS = 8;


    public Context context;
    public float mPreviousFoldFactor = 0;
    public float mFoldFactor = 0;
    public int mNumberOfFolds = 2;
    public Matrix[] mMatrix;
    public float [] mSrc;
    public float [] mDst;
    public Rect mDstRect;
    public boolean mIsFoldPrepared = false;
    public Paint mSolidShadow;
    public Paint mGradientShadow;
    public Orientation mOrientation = Orientation.HORIZONTAL;
    public boolean mIsHorizontal = true;
    public LinearGradient mShadowLinearGradient;
    public Matrix mShadowGradientMatrix;
    public float mAnchorFactor = 0;
    public int mOriginalWidth = 0;
    public int mOriginalHeight = 0;
    public View mView;
    public Rect[] mFoldRectArray;
    public float mFoldMaxWidth = 0;
    public float mFoldMaxHeight = 0;
    public float mFoldDrawWidth = 0;
    public float mFoldDrawHeight = 0;


    public AntareyAnimation (Context context)
    {
        this.context = context;
    }

    private void prepareFold(Orientation orientation, float anchorFactor, int numberOfFolds,View view) {

        mSrc = new float[NUM_OF_POLY_POINTS];
        mDst = new float[NUM_OF_POLY_POINTS];

        mDstRect = new Rect();

        mFoldFactor = 0;
        mPreviousFoldFactor = 0;

        mIsFoldPrepared = false;

        mSolidShadow = new Paint();
        mGradientShadow = new Paint();

        mOrientation = orientation;
        mIsHorizontal = (orientation == Orientation.HORIZONTAL);

        if (mIsHorizontal) {
            mShadowLinearGradient = new LinearGradient(0, 0, SHADING_FACTOR, 0, Color.BLACK,
                    Color.TRANSPARENT, Shader.TileMode.CLAMP);
        } else {
            mShadowLinearGradient = new LinearGradient(0, 0, 0, SHADING_FACTOR, Color.BLACK,
                    Color.TRANSPARENT, Shader.TileMode.CLAMP);
        }

        mGradientShadow.setStyle(Paint.Style.FILL);
        mGradientShadow.setShader(mShadowLinearGradient);
        mShadowGradientMatrix = new Matrix();

        mAnchorFactor = anchorFactor;
        mNumberOfFolds = numberOfFolds;

        mOriginalWidth = view.getMeasuredWidth();
        mOriginalHeight = view.getMeasuredHeight();

        mFoldRectArray = new Rect[mNumberOfFolds];
        mMatrix = new Matrix [mNumberOfFolds];

        for (int x = 0; x < mNumberOfFolds; x++) {
            mMatrix[x] = new Matrix();
        }

        int h = mOriginalHeight;
        int w = mOriginalWidth;

        int delta = Math.round(mIsHorizontal ? ((float) w) / ((float) mNumberOfFolds) :
                ((float) h) /((float) mNumberOfFolds));

        for (int x = 0; x < mNumberOfFolds; x++) {
            if (mIsHorizontal) {
                int deltap = (x + 1) * delta > w ? w - x * delta : delta;
                mFoldRectArray[x] = new Rect(x * delta, 0, x * delta + deltap, h);
            } else {
                int deltap = (x + 1) * delta > h ? h - x * delta : delta;
                mFoldRectArray[x] = new Rect(0, x * delta, w, x * delta + deltap);
            }
        }

        if (mIsHorizontal) {
            mFoldMaxHeight = h;
            mFoldMaxWidth = delta;
        } else {
            mFoldMaxHeight = delta;
            mFoldMaxWidth = w;
        }
    }

    private void calculateMatrices() {


        if (mFoldFactor == 1) {
            return;
        }

        mPreviousFoldFactor = mFoldFactor;

        for (int x = 0; x < mNumberOfFolds; x++) {
            mMatrix[x].reset();
        }

        float cTranslationFactor = 1 - mFoldFactor;

        float translatedDistance = mIsHorizontal ? mOriginalWidth * cTranslationFactor :
                mOriginalHeight * cTranslationFactor;

        float translatedDistancePerFold = Math.round(translatedDistance / mNumberOfFolds);
        mFoldDrawWidth = mFoldMaxWidth < translatedDistancePerFold ?
                translatedDistancePerFold : mFoldMaxWidth;
        mFoldDrawHeight = mFoldMaxHeight < translatedDistancePerFold ?
                translatedDistancePerFold : mFoldMaxHeight;

        float translatedDistanceFoldSquared = translatedDistancePerFold * translatedDistancePerFold;

        float depth = mIsHorizontal ?
                (float)Math.sqrt((double)(mFoldDrawWidth * mFoldDrawWidth -
                        translatedDistanceFoldSquared)) :
                (float)Math.sqrt((double)(mFoldDrawHeight * mFoldDrawHeight -
                        translatedDistanceFoldSquared));

        float scaleFactor = DEPTH_CONSTANT / (DEPTH_CONSTANT + depth);

        float scaledWidth, scaledHeight, bottomScaledPoint, topScaledPoint, rightScaledPoint,
                leftScaledPoint;

        if (mIsHorizontal) {
            scaledWidth = mFoldDrawWidth * cTranslationFactor;
            scaledHeight = mFoldDrawHeight * scaleFactor;
        } else {
            scaledWidth = mFoldDrawWidth * scaleFactor;
            scaledHeight = mFoldDrawHeight * cTranslationFactor;
        }

        topScaledPoint = (mFoldDrawHeight - scaledHeight) / 2.0f;
        bottomScaledPoint = topScaledPoint + scaledHeight;

        leftScaledPoint = (mFoldDrawWidth - scaledWidth) / 2.0f;
        rightScaledPoint = leftScaledPoint + scaledWidth;

        float anchorPoint = mIsHorizontal ? mAnchorFactor * mOriginalWidth :
                mAnchorFactor * mOriginalHeight;


        float midFold = mIsHorizontal ? (anchorPoint / mFoldDrawWidth) : anchorPoint /
                mFoldDrawHeight;

        mSrc[0] = 0;
        mSrc[1] = 0;
        mSrc[2] = 0;
        mSrc[3] = mFoldDrawHeight;
        mSrc[4] = mFoldDrawWidth;
        mSrc[5] = 0;
        mSrc[6] = mFoldDrawWidth;
        mSrc[7] = mFoldDrawHeight;

        for (int x = 0; x < mNumberOfFolds; x++) {

            boolean isEven = (x % 2 == 0);

            if (mIsHorizontal) {
                mDst[0] = (anchorPoint > x * mFoldDrawWidth) ? anchorPoint + (x - midFold) *
                        scaledWidth : anchorPoint - (midFold - x) * scaledWidth;
                mDst[1] = isEven ? 0 : topScaledPoint;
                mDst[2] = mDst[0];
                mDst[3] = isEven ? mFoldDrawHeight: bottomScaledPoint;
                mDst[4] = (anchorPoint > (x + 1) * mFoldDrawWidth) ? anchorPoint + (x + 1 - midFold)
                        * scaledWidth : anchorPoint - (midFold - x - 1) * scaledWidth;
                mDst[5] = isEven ? topScaledPoint : 0;
                mDst[6] = mDst[4];
                mDst[7] = isEven ? bottomScaledPoint : mFoldDrawHeight;

            } else {
                mDst[0] = isEven ? 0 : leftScaledPoint;
                mDst[1] = (anchorPoint > x * mFoldDrawHeight) ? anchorPoint + (x - midFold) *
                        scaledHeight : anchorPoint - (midFold - x) * scaledHeight;
                mDst[2] = isEven ? leftScaledPoint: 0;
                mDst[3] = (anchorPoint > (x + 1) * mFoldDrawHeight) ? anchorPoint + (x + 1 -
                        midFold) * scaledHeight : anchorPoint - (midFold - x - 1) * scaledHeight;
                mDst[4] = isEven ? mFoldDrawWidth : rightScaledPoint;
                mDst[5] = mDst[1];
                mDst[6] = isEven ? rightScaledPoint : mFoldDrawWidth;
                mDst[7] = mDst[3];
            }

            for (int y = 0; y < 8; y ++) {
                mDst[y] = Math.round(mDst[y]);
            }

            if (mIsHorizontal) {
                if (mDst[4] <= mDst[0] || mDst[6] <= mDst[2]) {
                    return;
                }
            } else {
                if (mDst[3] <= mDst[1] || mDst[7] <= mDst[5]) {
                    return;
                }
            }

            mMatrix[x].setPolyToPoly(mSrc, 0, mDst, 0, NUM_OF_POLY_POINTS / 2);
        }

        int alpha = (int) (mFoldFactor * 255 * SHADING_ALPHA);

        mSolidShadow.setColor(Color.argb(alpha, 0, 0, 0));

        if (mIsHorizontal) {
            mShadowGradientMatrix.setScale(mFoldDrawWidth, 1);
            mShadowLinearGradient.setLocalMatrix(mShadowGradientMatrix);
        } else {
            mShadowGradientMatrix.setScale(1, mFoldDrawHeight);
            mShadowLinearGradient.setLocalMatrix(mShadowGradientMatrix);
        }

        mGradientShadow.setAlpha(alpha);
    }

    public void TransformFold(float foldFactor,View view)
    {
        mAnchorFactor=1;
        mOrientation=Orientation.HORIZONTAL;
        mNumberOfFolds=2;
        prepareFold(mOrientation, mAnchorFactor, mNumberOfFolds,view);

        mFoldFactor=foldFactor;


        Bitmap returnedBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(returnedBitmap);

        if ( mFoldFactor == 0) {
            view.draw(canvas);
            return;
        }

        Rect src;

        for (int x = 0; x < mNumberOfFolds; x++) {
            src = mFoldRectArray[x];
            canvas.save();

            calculateMatrices();

            canvas.concat(mMatrix[x]);
            canvas.clipRect(0, 0, src.right - src.left, src.bottom - src.top);


            if (mIsHorizontal) {
                canvas.translate(-src.left, 0);
            } else {
                canvas.translate(0, -src.top);
            }



            view.draw(canvas);

            if (mIsHorizontal) {
                canvas.translate(src.left, 0);
            } else {
                canvas.translate(0, src.top);
            }



            if (x % 2 == 0) {
                canvas.drawRect(0, 0, mFoldDrawWidth, mFoldDrawHeight, mSolidShadow);

            } else {
                canvas.drawRect(0, 0, mFoldDrawWidth, mFoldDrawHeight, mGradientShadow);

            }
            canvas.restore();
        }



    }






}
Вызов

Код: Выделить всё

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        myListView = (ListView) findViewById(R.id.listView);

        String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
                "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
                "Linux", "OS/2" };
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, values);
        myListView.setAdapter(adapter);

        mTextView=(TextView)findViewById(R.id.textView);

        mAnchorSeekBar = (SeekBar)findViewById(R.id.seekBar);
        mAnchorSeekBar.setOnSeekBarChangeListener(mSeekBarChangeListener);
        mAntareyAnimation=new AntareyAnimation(getApplicationContext());

    }

Код: Выделить всё

    private SeekBar.OnSeekBarChangeListener mSeekBarChangeListener = new SeekBar
            .OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

            mAntareyAnimation.TransformFold(((float)mAnchorSeekBar.getProgress())/100.0f,myListView);
        }
    };

Но в сожалению ничего не происходит.
Прошу помощи в общественности
Заранее всем благодарен
Последний раз редактировалось antarey 24 июл 2014, 15:44, всего редактировалось 2 раза.

antarey
Сообщения: 6
Зарегистрирован: 23 июл 2014, 10:30

Re: Эффект складывания листа бумаги

Сообщение antarey » 23 июл 2014, 14:12

Или же как вариант - как назначить конкретному View конкретное событие - в с++билдер это бы выглядело примерно так
view->OndispatchDraw=dispatchDraw; как ето на яве???

Ответить