Search code examples
androidanimationnative-codemotion

how to handle animation for a label to let it be always inside screen borders in android?


I want to know a little in gaming world, so i'm trying first to create a graphical object that will start sliding with touch listener and when it arrives to the screen borders it will be translated in another side to let it be always visible. i know that i must put a runnable or thread inside my code, but first i should not let the object pass the screen borders.

any idea how to continue ?

public class MainActivity extends Activity implements OnTouchListener{

TextView _view;
ViewGroup _root;
private int _xDelta;
private int _yDelta;
private int X1,X2, Y1,Y2;


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

    _root = (ViewGroup) findViewById(R.id.root);
    _view = (TextView) findViewById(R.id.tv1);

    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(150, 50);
    layoutParams.leftMargin = 50;
    layoutParams.topMargin = 50;
    layoutParams.bottomMargin = -250;
    layoutParams.rightMargin = -250;
    _view.setLayoutParams(layoutParams);

    _view.setOnTouchListener(this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.page_refresh) {
        Intent i = new Intent(this,MainActivity.class);
        startActivity(i);
        this.finish();
        }
    return super.onOptionsItemSelected(item);
}

@Override
public boolean onTouch(View view, MotionEvent event) {
    final int X = (int) event.getRawX();
    final int Y = (int) event.getRawY();
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
        RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
        X1 = X;
        Y1 = Y;
        _xDelta = X - lParams.leftMargin;
        _yDelta = Y - lParams.topMargin;
        break;
    case MotionEvent.ACTION_UP:
        break;
    case MotionEvent.ACTION_POINTER_DOWN:
        break;
    case MotionEvent.ACTION_POINTER_UP:
        break;
    case MotionEvent.ACTION_MOVE:
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
        layoutParams.leftMargin = X - _xDelta;
        layoutParams.topMargin = Y - _yDelta;
        layoutParams.rightMargin = -250;
        layoutParams.bottomMargin = -250;
        X2 = X;
        Y2 = Y;
     /*   view.setX(X - _xDelta);
        view.setY(Y - _yDelta);
        view.setLayoutParams(view.getLayoutParams());*/
        view.setLayoutParams(layoutParams);
        if(X1 < X2)
            view.animate().translationX(X+5).translationY(getTransY(X));
        else if(X1 > X2)
            view.animate().translationX(X-5).translationY(getTransY(X));
        else {
            if(Y1 < Y2)/*Math.max(Math.abs(Y1), Math.abs(Y2))*/
                view.animate().translationY(Y-5);
            else view.animate().translationY(Y+5);
            }
        break;
} 
_root.invalidate();
return true;
}

public float getTransY(float x){
    float k = (Y2-Y1)/(X2-X1);
    return k*x;
}

}

Solution

  • You need to check width and height before changing LayoutParams and before animating as the following:

    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    
    float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
    float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
    
    if (X - _xDelta - view.getWidth() < dpWidth)
       layoutParams.leftMargin = X - _xDelta - view.getWidth();
    else
       layoutParams.leftMargin = dpWidth - view.getWidth();
    
    
    //Repeat same logic for Y and animation X+5 and Y+5 etc