2016-12-16 8 views
0

私はジョイスティックボタンを開発中です。サークルの周りを動かすときはすべてが問題ありませんが、上下に動かしたいときは、右からもう一度円の周りを移動します。だから、私は両方のオプション(実際のジョイスティックのように円で上下に移動する)を持っていたい。ここに私のコード例があります。おかげで任意のヘルプImageView onTouchは上下に動かず、円の周りのみです

public class JoystickView extends FrameLayout implements View.OnTouchListener { 

    private Context context; 
    private ImageView backgroundImageView; 
    private ImageView buttonImageView; 
    private RelativeLayout relativeLayout; 
    private View rootView; 
    float xx = 0; 
    float yy = 0; 



    public JoystickView(Context context) { 
     super(context); 
     this.context = context; 
     setLayout(this); 
     buttonImageView.setOnTouchListener(this); 
     this.setClipChildren(false); 

    } 

    public void setLayout(ViewGroup view) { 

     FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 
     View v = inflateControlerLayout(); 
     view.addView(v, layoutParams); 
    } 

    protected View inflateControlerLayout() { 
     initSlider(); 
     rootView = relativeLayout; 
     return rootView; 

    } 


    public void initSlider() { 

     if (relativeLayout == null) { 
      relativeLayout = new RelativeLayout(context); 
      RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); 
      relativeLayout.setLayoutParams(layoutParams); 
      relativeLayout.setClipChildren(false); 
     } 

     if (backgroundImageView == null) { 
      backgroundImageView = new ImageView(context); 

      LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); 
      backgroundImageView.setLayoutParams(layoutParams); 

      // load image 
      try { 
       // get input stream 
       InputStream ims = getContext().getAssets().open("joystick_background.png"); 
       // load image as Drawable 
       Drawable d = Drawable.createFromStream(ims, null); 
       // set image to ImageView 
       backgroundImageView.setImageDrawable(d); 
      } catch (IOException ex) { 
       return; 
      } 
     } 

     if (buttonImageView == null) { 
      buttonImageView = new ImageView(context); 

      LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, Gravity.CENTER); 

      buttonImageView.setLayoutParams(layoutParams); 


      // load image 
      try { 
       // get input stream 
       InputStream ims2 = getContext().getAssets().open("jostick_button.png"); 
       // load image as Drawable 
       Drawable d2 = Drawable.createFromStream(ims2, null); 
       // set image to ImageView 
       buttonImageView.setImageDrawable(d2); 
       buttonImageView.bringToFront(); 
      } catch (IOException ex) { 
       return; 
      } 
     } 

     if (relativeLayout != null) { 
      relativeLayout.addView(backgroundImageView); 
      relativeLayout.addView(buttonImageView); 
     } 
    } 

    @Override 
    public boolean onTouch(View view, MotionEvent motionEvent) { 


     switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { 
      case MotionEvent.ACTION_DOWN: 

       break; 

      case MotionEvent.ACTION_UP: 
       view.setX(xx); 
       view.setY(yy); 
       break; 

      case MotionEvent.ACTION_POINTER_DOWN: 
       break; 

      case MotionEvent.ACTION_POINTER_UP: 
       break; 

      case MotionEvent.ACTION_MOVE: 


       float cx = view.getWidth()/2.f; 
       float cy = view.getHeight()/2.f; 
       float x = motionEvent.getRawX(); 
       float y = motionEvent.getRawY(); 
       float w = buttonImageView.getWidth(); 
       float h = buttonImageView.getHeight(); 

       double r = Math.min(cx, cy)/2.; 
       double dx = x - cx; 
       double dy = y - cy; 
       double hypot = Math.hypot(dx, dy); 
       double cos = dx/hypot; 
       double sin = dy/hypot; 
       double rdx = hypot < 1. ? 0. : r * cos; 
       double rdy = hypot < 1. ? 0. : r * sin; 

       buttonImageView.setTranslationX((float) (cx + rdx - w/2.)); 
       buttonImageView.setTranslationY((float) (cy + rdy - h/2.)); 

       break; 
     } 
     return true; 

    } 
} 

答えて

1

のためにこれらの行は、円(楕円形)パスまたは中央に座標を制約:hypot 1未満であるためには

  double rdx = hypot < 1. ? 0. : r * cos; 
      double rdy = hypot < 1. ? 0. : r * sin; 

(つまり、1つのピクセルです)あなたがする必要があるだろう死んだ中心になる。

私は唯一の円内の座標を制約し、それを変更:

  double rcos = r * cos; 
      double rsin = r * sin; 
      double rdx = Math.abs(dx) < Math.abs(rcos) ? dx : rcos; 
      double rdy = Math.abs(dy) < Math.abs(rsin) ? dy : rsin; 

私は、これはあなたが望むかもしれないと思います。誰かがそれ

プライベートポイントの計算(フロートX、フロートY){

float cx = buttonImageView.getWidth()/2.f; 
    float cy = buttonImageView.getHeight()/2.f; 

    double r = cx/2.; // vrednost radius 
    double dx = x; 
    double dy = y; 
    double hypot = Math.hypot(dx, dy); // izracun hipotenuze 
    double cos = dx/hypot; // cos 
    double sin = dy/hypot; // sin 

    double rcos = r * cos; 
    double rsin = r * sin; 

    double rdx = Math.abs(dx) < Math.abs(rcos) ? dx : rcos; // if,else 
    double rdy = Math.abs(dy) < Math.abs(rsin) ? dy : rsin; 

    return new Point((int)rdx, (int)rdy); 

} 

@Override 
public boolean onTouch(View view, MotionEvent motionEvent) { 


    final float x = motionEvent.getRawX(); // x točko 
    final float y = motionEvent.getRawY(); // y točka 

    //Log.d("VALUES", "RAW X:" + motionEvent.getRawX() + ", RAW Y:" + motionEvent.getRawY() + ", X:" + motionEvent.getX() + ", CX:" + cx + ", CY:" + cy + ", dx:" + dx + ", dy:" + dy + ", Hypo:" + hypot + ", cos:" + cos + ", sin" + sin); 


    switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { 
     case MotionEvent.ACTION_DOWN: 

      xDelta = view.getX() - x; 
      yDelta = view.getY() - y; 

      break; 

     case MotionEvent.ACTION_UP: 

      doBounceAnimation(buttonImageView); 
      doVibration(); 

      view.setX(xx); 
      view.setY(yy); 
      break; 

     case MotionEvent.ACTION_POINTER_DOWN: 
      break; 

     case MotionEvent.ACTION_POINTER_UP: 
      break; 

     case MotionEvent.ACTION_MOVE: 

      final float transX = (float) x; 
      final float transY = (float) y; 

      thread = new Thread() { 
       @Override 
       public void run() { 

        Point newPoint = calculate(transX+ xDelta,transY + yDelta); 
        buttonImageView.setX(newPoint.x); 
        buttonImageView.setY(newPoint.y); 
       } 
      }; 
      thread.start(); 




      Log.d(TRANSLATIONX,"X:" + transX + ", Y:" + transY); 

      break; 

    } 
    return true; 

} 

を探している場合

+0

こんにちはkris、すみません、ありがとう、それは動作します!さて、それは私が問題であったことをより意味がわかります。しかし、今私は別のものを扱っています。私はそれについてのあなたの考えを聞きたい:それはうまく動作し、私は今、上下にボタンを移動することができます。しかし、今私はそれを中央に指で触れ、それを移動しようとすると、ボタンが右下に移動)、指の中央の先端がボタンの左隅にあります。とにかく、あなたの解決に感謝します。 –

+0

私はその動作に気づいた。コードは円を描いてビューを動かすように調整されているため、ダイヤルや何かを回転させるためのコードスニペットを使い始める必要があると思います。あなたが望む振る舞いを得るためには、最初のx/y座標をポインターダウンイベントに保存してから、ポインター移動イベントの相対移動を導き出すことができます。これらの変更を自分で行ってください。立ち往生した場合は、コミュニティの別の質問を投稿してください。 –

+0

サンクスクリス(ヘルプ)私は解決策を見つけました。 –

0

は、私は実用的なソリューションを発見したコーディングをお楽しみください!

関連する問題