복붙노트

[SPRING] 리바운드 라이브러리를 사용하여 Facebook Messenger 채팅 헤드와 동일한 ImageView에 자연스러운 끌기 효과 추가

SPRING

리바운드 라이브러리를 사용하여 Facebook Messenger 채팅 헤드와 동일한 ImageView에 자연스러운 끌기 효과 추가

나는 ImageView 내에서 드래그하는 앱을 개발 중이다. Facebook 메신저의 채팅 헤드 애니메이션에 원래 사용 된 스프링 애니메이션 용 Facebook Rebound 라이브러리를 구성했습니다. 드래그 할 때 이러한 종류의 애니메이션을 ImageView에 추가하고 싶습니다.   비디오

지금까지 ImageView (스프링 뷰가 구현 된 스프링)를 터치하면 스프링 애니메이션을 얻을 수 있습니다. 이것이 내 코드입니다. ImageView에 자연스러운 드래그 효과를 어떻게 구현할 수 있습니까?

public class MainTry extends Activity {

    int windowwidth;
    int windowheight;

    private LayoutParams layoutParams;
    private final BaseSpringSystem mSpringSystem = SpringSystem.create();
    private FrameLayout mRootView;
    private Spring spring;
    private View mImageView;
    private VelocityTracker velocity = null;
    private float dx;
    private float dy;
    private View rootView;
    private ImageView img;

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

    // Create a system to run the physics loop for a set of springs.
    SpringSystem springSystem = SpringSystem.create();

    // Add a spring to the system.
    spring = springSystem.createSpring();

    rootView = getWindow().getDecorView()
            .findViewById(android.R.id.content);

    windowwidth = getWindowManager().getDefaultDisplay().getWidth();
    windowheight = getWindowManager().getDefaultDisplay().getHeight();
    img = (ImageView) findViewById(R.id.imageView2);

    rootView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // spring.setEndValue(1);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                // spring.setEndValue(0);
                break;
            }
            return true;
        }
    });
    // Add a listener to observe the motion of the spring.
    spring.addListener(new SimpleSpringListener() {

        @Override
        public void onSpringUpdate(Spring spring) {
            // You can observe the updates in the spring
            // state by asking its current value in onSpringUpdate.
            float value = (float) spring.getCurrentValue();
            float scale = .5f - (value * 0.1f);
            img.setScaleX(scale);
            img.setScaleY(scale);
        }
    });
    // spring.setEndValue(1);

    img.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            LayoutParams layoutParams = (LayoutParams) img
                    .getLayoutParams();

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                dx = event.getRawX() - 10;
                dy = event.getRawY() - 10;

                if (velocity == null) {
                    // Retrieve a new VelocityTracker object to watch the
                    // velocity of a motion.
                    velocity = VelocityTracker.obtain();
                } else {
                    // Reset the velocity tracker back to its initial state.
                    velocity.clear();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                dx = event.getRawX() - 10;
                dy = event.getRawY() - 10;


                velocity.addMovement(event);
                spring.setVelocity(velocity.getYVelocity());
                spring.setCurrentValue(dy);
                spring.setEndValue(dy);


                layoutParams.leftMargin = (int) dx - 10;
                layoutParams.topMargin = (int) dy - 10;
                img.setLayoutParams(layoutParams);
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
            case MotionEvent.ACTION_UP:
                velocity.addMovement(event);
                spring.setVelocity(velocity.getYVelocity());
                spring.setCurrentValue(event.getRawY() - 10);
                spring.setEndValue(0);

                break;

            default:
                break;
            }
            return true;
        }
    });

}

@Override
public void onResume() {
    super.onResume();
}

@Override
public void onPause() {
    super.onPause();
}


}

해결법

  1. ==============================

    1.이건 어때?

    이건 어때?

    class V extends View implements SpringListener {
        private static final int NUM_ELEMS = 4;
        private Spring[] mXSprings = new Spring[NUM_ELEMS];
        private Spring[] mYSprings = new Spring[NUM_ELEMS];
        private Paint mPaint = new Paint();
        private Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
    
        public V(Context context) {
            super(context);
            SpringSystem ss = SpringSystem.create();
    
            Spring s;
            for (int i = 0; i < NUM_ELEMS; i++) {
                s = ss.createSpring();
                s.setSpringConfig(new MySpringConfig(200, i == 0? 8 : 15 + i * 2, i, true));
                s.addListener(this);
                mXSprings[i] = s;
    
                s = ss.createSpring();
                s.setSpringConfig(new MySpringConfig(200, i == 0? 8 : 15 + i * 2, i, false));
                s.addListener(this);
                mYSprings[i] = s;
            }
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            mXSprings[0].setCurrentValue(w / 2);
            mYSprings[0].setCurrentValue(0);
    
            mXSprings[0].setEndValue(w / 2);
            mYSprings[0].setEndValue(h / 2);
        }
    
        @Override
        public void onSpringActivate(Spring s) {
        }
    
        @Override
        public void onSpringAtRest(Spring s) {
        }
    
        @Override
        public void onSpringEndStateChange(Spring s) {
        }
    
        @Override
        public void onSpringUpdate(Spring s) {
            MySpringConfig cfg = (MySpringConfig) s.getSpringConfig();
            if (cfg.index < NUM_ELEMS - 1) {
                Spring[] springs = cfg.horizontal? mXSprings : mYSprings;
                springs[cfg.index + 1].setEndValue(s.getCurrentValue());
            }
            if (cfg.index == 0) {
                invalidate();
            }
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            mXSprings[0].setEndValue(event.getX());
            mYSprings[0].setEndValue(event.getY());
            return true;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            for (int i = NUM_ELEMS - 1; i >= 0; i--) {
                mPaint.setAlpha(i == 0? 255 : 192 - i * 128 / NUM_ELEMS);
                canvas.drawBitmap(mBitmap, 
                        (float) mXSprings[i].getCurrentValue() - mBitmap.getWidth() / 2,
                        (float) mYSprings[i].getCurrentValue() - mBitmap.getHeight() / 2,
                        mPaint);
            }
        }
    
        class MySpringConfig extends SpringConfig {
            int index;
            boolean horizontal;
            public MySpringConfig(double tension, double friction, int index, boolean horizontal) {
                super(tension, friction);
                this.index = index;
                this.horizontal = horizontal;
            }
        }
    }
    
  2. ==============================

    2.나는 위의 V 클래스를 Window-manager에서 직접 사용했고 완벽하게 작동했으며 chathead는 facebook 메신저처럼 움직인다.

    나는 위의 V 클래스를 Window-manager에서 직접 사용했고 완벽하게 작동했으며 chathead는 facebook 메신저처럼 움직인다.

    public class ChatHeadService extends Service
    {
    
        private LayoutInflater inflater;
        private WindowManager windowManager;
    
        private Point szWindow = new Point();
    
    
        @Override
        public void onCreate()
        {
        super.onCreate();
        Log.v(Utils.LogTag, "Start Service");
        }
    
        private
        void handleStart(){
    
             windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
            inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
    
            if (Build . VERSION . SDK_INT >= Build . VERSION_CODES . HONEYCOMB) {
                windowManager . getDefaultDisplay() . getSize(szWindow);
            } else {
                int w = windowManager . getDefaultDisplay() . getWidth();
                int h = windowManager . getDefaultDisplay() . getHeight();
                szWindow . set(w, h);
            }
    
            WindowManager . LayoutParams params = new WindowManager . LayoutParams(
                WindowManager . LayoutParams . WRAP_CONTENT,
                WindowManager . LayoutParams . WRAP_CONTENT,
                WindowManager . LayoutParams . TYPE_PHONE,
                WindowManager . LayoutParams . FLAG_NOT_FOCUSABLE |
                WindowManager . LayoutParams . FLAG_WATCH_OUTSIDE_TOUCH |
                WindowManager . LayoutParams . FLAG_LAYOUT_NO_LIMITS,
                PixelFormat . TRANSLUCENT
            );
    
            params . gravity = Gravity . TOP | Gravity . LEFT;
            params . x       = 50;
            params . y       = 100;
    
            V vImg = new V(this);
    
            windowManager . addView(vImg, params);
    
    
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            if (intent != null) {
                if (startId == Service . START_STICKY) {
                    handleStart();
                }
            }
    
            return super . onStartCommand(intent, flags, startId);
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onDestroy(){
                    super . onDestroy();
            if (windowManager != null) {
                // windowManager.removeView(chatHeadView);
            }
        }
    }
    
  3. from https://stackoverflow.com/questions/23976343/adding-natural-dragging-effect-to-imageview-same-as-facebook-messanger-chat-head by cc-by-sa and MIT license