Android 使用回弹库向ImageView添加与Facebook Messanger聊天头相同的自然拖动效果
我正在开发一个应用程序,其中我正在活动中拖动ImageView。 我已经为spring动画进行了配置,该动画最初用于Facebook Messenger的聊天头动画。我想在拖动ImageView时将此类动画添加到它。 到目前为止,我能够在触摸ImageView(在rootview上实现spring)时获得spring动画,这是我的代码。如何在ImageView中实现这种自然类型的拖动效果Android 使用回弹库向ImageView添加与Facebook Messanger聊天头相同的自然拖动效果,android,facebook,spring,animation,Android,Facebook,Spring,Animation,我正在开发一个应用程序,其中我正在活动中拖动ImageView。 我已经为spring动画进行了配置,该动画最初用于Facebook Messenger的聊天头动画。我想在拖动ImageView时将此类动画添加到它。 到目前为止,我能够在触摸ImageView(在rootview上实现spring)时获得spring动画,这是我的代码。如何在ImageView中实现这种自然类型的拖动效果 public class MainTry extends Activity { int wind
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();
}
}
那么这个呢:
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;
}
}
}
classv扩展视图实现SpringListener{
私有静态final int NUM_ELEMS=4;
私有弹簧[]mXSprings=新弹簧[NUM_ELEMS];
private Spring[]mYSprings=new Spring[NUM_ELEMS];
私有油漆mPaint=新油漆();
私有位图mBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_启动器);
公共V(上下文){
超级(上下文);
SpringSystem ss=SpringSystem.create();
春雨;
对于(int i=0;i=0;i--){
setAlpha(i==0?255:192-i*128/NUM_ELEMS);
画布.绘图位图(mBitmap,
(float)mXSprings[i].getCurrentValue()-mBitmap.getWidth()/2,
(float)mYSprings[i].getCurrentValue()-mBitmap.getHeight()/2,
mPaint);
}
}
类MySpringConfig扩展了SpringConfig{
整数指数;
布尔水平;
public MySpringConfig(双张力、双摩擦、整数索引、布尔水平){
超级(张力、摩擦);
这个指数=指数;
这个水平=水平;
}
}
}
我在Window manager中直接使用了上面的V类,它的工作非常完美,聊天头的移动就像facebook messenger一样
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);
}
}
}
嗨,pskink,一旦我创建了类(上面的代码),我该如何使用它呢?你能分享一下我们如何使用你的班级吗?谢谢我试着让我看到的只是图像。它不会拖。我遗漏了什么吗?@supret你在模拟器/设备上运行了代码吗?嗨@pskink我不能在模拟器或设备上运行你的代码,因为我们在Android开发中不使用java。我们使用Xamarin.android&我在C#中移植了您的代码(一字不差,一行一行)。我共享的图像在一个模拟器中,来自移植的代码。我得到了它。我们唯一没有实现的是在索引为0时在SpringUpdate上失效。这就是诀窍。谢谢你这么棒的代码。这很好用!一件事是,当你触摸屏幕时,比如打开一个新的应用程序/在主页上滑动,浮动图标会到达你触摸的地方,阻止其他事件。如何防止这种情况?意味着只有当您触摸图标本身时,事件触发显示才能通过像Facebook messenger聊天头一样拖动屏幕底部来删除聊天头?