Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android幻灯片回答类似ImageView动画_Android_Imageview_Android Animation - Fatal编程技术网

Android幻灯片回答类似ImageView动画

Android幻灯片回答类似ImageView动画,android,imageview,android-animation,Android,Imageview,Android Animation,我需要在图像视图上实现一个动画,类似于许多Android设备中存在的幻灯片回答动画。 要求: 支持API级别>=8(如果不可能,则为9),因此方便是不可能的 拖动图像视图时,将其向右或向左移动,仅需要水平拖动。首先,图像水平居中 拖动时缩放图像视图——越靠近屏幕末端,图像越小 释放拖动时,图像需要设置动画回到屏幕中心,并缩放到其原始大小(也设置动画) 我找到了很多代码示例,并试图自己实现,但所有要求的结合使得实现非常困难,我无法得到一个合适的结果,因此请不要在Google搜索的第一页上添加指向内

我需要在图像视图上实现一个动画,类似于许多Android设备中存在的幻灯片回答动画。 要求:

  • 支持API级别>=8(如果不可能,则为9),因此方便是不可能的
  • 拖动图像视图时,将其向右或向左移动,仅需要水平拖动。首先,图像水平居中
  • 拖动时缩放图像视图——越靠近屏幕末端,图像越小
  • 释放拖动时,图像需要设置动画回到屏幕中心,并缩放到其原始大小(也设置动画)

  • 我找到了很多代码示例,并试图自己实现,但所有要求的结合使得实现非常困难,我无法得到一个合适的结果,因此请不要在Google搜索的第一页上添加指向内容的链接,因为我已经花了很多天的时间尝试实现这些示例,我希望您能提供一个工作代码示例+xml布局(如果需要)

    您可以通过结合以下内容来做到这一点,而不会太复杂:

    • A(为了检测拖动顺序,基本上是
      动作向下
      动作向上移动
      ,…,
      动作向上
    • Jake Wharton的优秀库,支持API级别11之前的视图属性动画
    首先,获取
    ImageView
    对象并将
    View.OnTouchListener
    附加到该对象上

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
    
        ...
        mImage = findViewById(...);
        mImage.setOnTouchListener(mTouchListener);
    }
    
    其次,编程
    OnTouchListener
    以捕获
    动作向下
    事件并存储初始触摸位置X坐标。然后,对于每个
    操作_MOVE
    计算增量(用于平移和缩放),对于
    操作_UP
    将ImageView返回到其初始状态

    private View.OnTouchListener mTouchListener = new View.OnTouchListener()
    {
        private float mStartX;
    
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            switch (event.getActionMasked())
            {
                case MotionEvent.ACTION_DOWN :
                    mStartX = event.getRawX();
                    return true;
    
                case MotionEvent.ACTION_MOVE :
                    float currentX = event.getRawX();
                    animateTo(currentX - mStartX, true); // Snap to drag
                    return true;
    
                case MotionEvent.ACTION_UP :
                case MotionEvent.ACTION_CANCEL :
                    animateTo(0, false); // Ease back
                    return true;
            }
    
            return false;
        }
    };
    
    animateTo()
    将按如下方式实现。
    immediate
    标志指示平移和缩放是否应该是立即的(在响应每个移动事件时为真,在返回初始位置和缩放时为假)

    您可能需要修改缩放。如前所述,这意味着将图像拖到屏幕边界时,图像将保持其原始大小的50%


    这个解决方案在API级别8中应该可以正常工作(尽管我还没有测试它)。完整的要点是您是否需要它。

    首先想到的是通过
    处理程序为
    布局参数设置动画。不确定它是否符合您的要求,这可能需要更多的测试

    在任何情况下,记住数学都是非常有趣的^^^因此,我只使用本机android工具:

    代码:

    package com.example.simon.draggableimageview;
    导入android.os.Handler;
    导入android.support.v7.app.ActionBarActivity;
    导入android.os.Bundle;
    导入android.util.Log;
    导入android.view.MotionEvent;
    导入android.view.view;
    导入android.widget.ImageView;
    导入android.widget.RelativeLayout;
    /**
    *由Simon于2014年11月18日创建。
    */
    公共类MainActivity扩展了ActionBarActivity{
    私有静态最终字符串TAG=“MainActivity”;
    //避免以下两项的小值,否则setSize将开始滞后
    //动画(从最小)到默认大小所需的最大时间
    专用静态最终整数最大持续时间=500;
    //每个环路的最小延迟(ms)
    专用静态最终整数最小延迟=20;
    //每个(动画返回默认状态)循环将移动图像多少像素(至少)
    专用静态最终浮点最小值X移位=3;
    私有图像视图;
    米尼蒂亚尔、米尼蒂亚尔、麦肯特斯私人酒店;
    私有内部mMaxMargin;
    私人回溯式人体模型;
    私人经理人;
    @凌驾
    创建时受保护的void(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mHandler=新处理程序();
    mImage=(ImageView)findViewById(R.id.ImageView);
    最终RelativeLayout imageHolder=(RelativeLayout)findViewById(R.id.imageHolder);
    mImage.post(新的Runnable(){
    @凌驾
    公开募捐{
    //图像准备好了,测量一下
    mInitialH=mImage.getHeight();
    mInitialW=mImage.getWidth();
    imageHolder.post(新的Runnable(){
    @凌驾
    公开募捐{
    //计算其他测量值
    int containerWidth=imageHolder.getWidth();
    mCenterX=集装箱宽度/2;
    mMaxMargin=集装箱宽度-最小值;
    }
    });
    }
    });
    imageHolder.setOnTouchListener(新视图.OnTouchListener(){
    @凌驾
    公共布尔onTouch(视图、运动事件、运动事件){
    开关(motionEvent.getAction()){
    case MotionEvent.ACTION\u UP:
    case MotionEvent.ACTION\u取消:
    mAnimateBack=新的AnimateBack();
    mAnimateBack.run();
    打破
    case MotionEvent.ACTION\u移动:
    mHandler.removeCallbacks(假人背部);
    if(motionEvent.getX()>mMaxMargin+mInitialW | | motionEvent.getX()<0){
    //如果超出容器边界,则假装行动
    motionEvent.setAction(motionEvent.ACTION\u UP);
    onTouch(视图、运动事件);
    返回true;
    }
    设置大小(motionEvent.getX()-mCenterX);
    打破
    }
    返回true;
    }
    
    private void animateTo(float displacement, boolean immediate)
    {
        final int EASE_BACK_DURATION = 300; // ms
        int duration = (immediate ? 0 : EASE_BACK_DURATION);
    
        Display display = getWindowManager().getDefaultDisplay();
        int totalWidth = display.getWidth();
        float scale = 1.0f - Math.abs(displacement / totalWidth);
    
        ViewPropertyAnimator.animate(mImage)
            .translationX(displacement)
            .scaleX(scale)
            .scaleY(scale)
            .setDuration(duration)
            .start();
    }
    
    package com.example.simon.draggableimageview;
    
    import android.os.Handler;
    import android.support.v7.app.ActionBarActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    
    /**
     * Created by Simon on 2014 Nov 18.
     */
    
    public class MainActivity extends ActionBarActivity {
    
        private static final String TAG = "MainActivity";
    
        // Avoid small values for the following two or setSize will start lagging behind
        // The maximum time, animation (from smallest) to default size will take
        private static final int MAX_DURATION = 500;
        // Minimum delay (ms) for each loop
        private static final int MIN_DELAY = 20;
    
        // By how many px (at least) each (animation back to default state) loop will shift the image
        private static final float MIN_X_SHIFT = 3;
    
        private ImageView mImage;
        private int mInitialW, mInitialH, mCenterX;
        private int mMaxMargin;
        private AnimateBack mAnimateBack;
        private Handler mHandler;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mHandler = new Handler();
            mImage = (ImageView) findViewById(R.id.imageView);
            final RelativeLayout imageHolder = (RelativeLayout) findViewById(R.id.imageHolder);
    
            mImage.post(new Runnable() {
                @Override
                public void run() {
                    // Image ready, measure it
                    mInitialH = mImage.getHeight();
                    mInitialW = mImage.getWidth();
    
                    imageHolder.post(new Runnable() {
                        @Override
                        public void run() {
                            // Calc other measurements
                            int containerWidth = imageHolder.getWidth();
                            mCenterX = containerWidth / 2;
                            mMaxMargin = containerWidth - mInitialW;
                        }
                    });
                }
            });
    
            imageHolder.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    switch (motionEvent.getAction()) {
                        case MotionEvent.ACTION_UP:
                        case MotionEvent.ACTION_CANCEL:
                            mAnimateBack = new AnimateBack();
                            mAnimateBack.run();
                            break;
                        case MotionEvent.ACTION_MOVE:
                            mHandler.removeCallbacks(mAnimateBack);
                            if (motionEvent.getX() > mMaxMargin + mInitialW || motionEvent.getX() < 0) {
                                // Fake Action_Up if out of container bounds
                                motionEvent.setAction(MotionEvent.ACTION_UP);
                                onTouch(view, motionEvent);
                                return true;
                            }
                            setSize(motionEvent.getX() - mCenterX);
                            break;
                    }
                    return true;
                }
            });
        }
    
        private void setSize(float offsetFromCenter) {
            // Calculate new left margin
            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mImage.getLayoutParams();
            params.leftMargin = (int) (mMaxMargin * offsetFromCenter / (mCenterX - mInitialW / 2.0));
    
            // Calculate dimensions
            float ratio = 1 - (Math.abs(offsetFromCenter) / mCenterX);
            params.width = (int) (mInitialW * ratio);
            params.height = (int) (mInitialH * ratio);
            mImage.setLayoutParams(params);
    
    //      Log.e(TAG, String.format("leftMargin: %d, W: %d, H: %d",
    //              params.leftMargin, params.width, params.height));
        }
    
        private class AnimateBack implements Runnable {
            private int loopCount, loopDelay;
            private float loopBy;
    
            public AnimateBack() {
                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mImage.getLayoutParams();
                float offsetFromCenter = (float) params.leftMargin / mMaxMargin *
                        (mCenterX - mInitialW / 2.0f);
                float totalDuration = (Math.abs(offsetFromCenter) * MAX_DURATION / mCenterX);
    
                loopBy = MIN_X_SHIFT;
                loopCount = (int) Math.abs(offsetFromCenter / loopBy);
                loopDelay = (int) (totalDuration / loopCount);
                if (loopDelay < MIN_DELAY) {
                    // Use the minimum delay
                    loopDelay = MIN_DELAY;
                    // Minimum loop count is 1
                    loopCount = (int) Math.max(totalDuration / loopDelay, 1);
                    // Calculate by how much each loop will inc/dec the margin
                    loopBy = Math.round(Math.abs(offsetFromCenter / loopCount));
                }
                Log.d(TAG, String.format("Animate back will take: %fms. Will start from offset %d. " +
                                "It will advance by %dpx every %dms",
                        totalDuration, (int) offsetFromCenter, (int) loopBy, loopDelay));
            }
    
            @Override
            public void run() {
                --loopCount;
                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mImage.getLayoutParams();
                // Calculate offsetFromCenter
                float offsetFromCenter = (float) ((float) params.leftMargin / mMaxMargin *
                        (mCenterX - mInitialW / 2.0));
                // Don't pass 0 when looping
                if (params.leftMargin > 0) {
                    offsetFromCenter = Math.max(offsetFromCenter - loopBy, 0);
                } else {
                    offsetFromCenter = Math.min(offsetFromCenter + loopBy, 0);
                }
                setSize(offsetFromCenter);
    
                if (loopCount == 0) {
                    mHandler.removeCallbacks(this);
                } else {
                    mHandler.postDelayed(this, loopDelay);
                }
            }
        }
    
    }
    
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <RelativeLayout
            android:id="@+id/imageHolder"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center">
    
            <ImageView
                android:id="@+id/imageView"
                android:layout_width="200dp"
                android:layout_height="200dp"
                android:src="@drawable/ic_launcher"/>
    
        </RelativeLayout>
    </RelativeLayout>