2

フルスクリーンのカスタム ギャラリーがあります。ギャラリーの要素には、ボタンやその他のインタラクティブな領域があります。一部のユーザー インターフェイスは、ギャラリーの前に表示されるダイアログ ボックスを介して行われます。ダイアログ ボックスが閉じられると、ユーザーはギャラリーに戻ります。

ほとんどの場合、これで問題なく動作します。ただし、ダイアログ ボックスを閉じた後、ボタンがユーザー入力を受け付けなくなることがあります。一方、ギャラリーはまだスクロールしています。さらに奇妙なことに、ギャラリーをスクロールするとすぐに、失敗したと思われるクリックがシステムによって処理されます (ダイアログのポップアップなど)。

メイン UI スレッドがロックされていると言うのは簡単です。なぜロックされているのですか?ロックを解除するにはどうすればよいですか?どんな助けでも大歓迎です。以下は、クラスの完全なコードです。

アップデート。 ギャラリー内の要素の 1 つにHorizontalScrollView. スクロールしようとすると、マウス メッセージが表示されます。それらを調べてみると、scrollBy()andinvalidate()が適切に呼び出されていることがわかりました。次に、メッセージ キューを出力しました。メイン ループを通過する唯一のイベントは 1006 で、これは Touch イベントだと思います。引き分けイベントである 1000 は決して成功しません。ギャラリーを前後にスクロールすると、見よ、メッセージ キューが 1000 の受信を開始するので、HorizontalScrollViewスクロールは正常に行われます。

では、問題は次のようになります: Draw イベントを停止するものは何ですか?また、それらがキューに確実に送信されるようにするにはどうすればよいでしょうか?

public class PlayerGallery extends Gallery
{
  // 4 buttons to display
  private final static int BUT_BIRD = 0;
  private final static int BUT_SCORE = 1;
  private final static int BUT_ROUND = 2;
  private final static int BUT_MOVE = 3;
  private final static int N_BUTTONS = 4;

  // button images
  private final static Drawable[] imgButtons =
  {
    WonDraw.WW.bird,
    WonDraw.WW.scores,
    WonDraw.WW.moveSumm,
    WonDraw.WW.lastMove,
  };

  // individual player views
  private PlayerView[] views;

  // card that was clicked in the current player view
  private Card clickedCard = null;

  // wonder that was clicked in the current player view
  private Player clickedWonderPlayer = null;

  // one player
  private final class PlayerView extends RelativeLayout
    implements OnClickListener
  {
    // base view ID for the buttons
    private final static int BUT_VIEW_ID = 200;

    // player to display
    final Player player;

    // drawing data
    private PlayerDisplay pd = null;

    // the sub-view on top that shows player's hand
    private HandView handView = null;

    // button that takes user into bird's view
    private final GlassButton[] buttons = new GlassButton[N_BUTTONS];

    public PlayerView(Player player)
    {
      super(WonActivity.W.getApplicationContext());
      setBackgroundColor(Color.TRANSPARENT);
      this.player = player;

      RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
          LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
      lp.addRule(ALIGN_PARENT_TOP);
      handView = new HandView();
      addView(handView, lp);

      for (int i = 0; i < buttons.length; ++i)
      {
        lp = new RelativeLayout.LayoutParams(
            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

        if (i % 2 == 0)
          lp.addRule(ALIGN_PARENT_RIGHT);
        else
          lp.addRule(LEFT_OF, buttons[i - 1].getId());

        lp.addRule(BELOW, i / 2 == 0 ? handView.getId() : buttons[i - 2].getId());
        GlassButton but = new ImgGlassButton(GlassButton.ROUND, imgButtons[i]);
        but.setId(BUT_VIEW_ID + i);
        but.setOnClickListener(this);
        buttons[i] = but; addView(but, lp);
      }
    }

    // reset for the next player
    void reset(boolean useBigCards)
    {
      pd = WonActivity.W.getDisplay(player.id, useBigCards);

      if (useBigCards)
      {
        handView.pd = pd;
        handView.hand = WonActivity.W.getCurrentHand();
        handView.setVisibility(VISIBLE);
        handView.requestLayout();
        handView.scrollTo(0, 0);
      }
      else
      {
        handView.pd = null;
        handView.hand = null;
        handView.setVisibility(GONE);
      }

      for (int i = BUT_ROUND; i <= BUT_MOVE; ++i)
        buttons[i].setEnabled(Table.T.movesAvailable());

      invalidate();
    }

    @Override
    protected void dispatchSetPressed(boolean pressed)
    {
      // if I don't do that, bird button gets pressed when I scroll the gallery!
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
      if (event.getAction() == MotionEvent.ACTION_DOWN)
      {
        int x = (int)event.getX();
        int y = (int)event.getY();

        clickedCard = pd.findSmallCard(x, y);
        clickedWonderPlayer = clickedCard == null && pd.isInWonder(x, y) ?
          player : null;
      }
      return super.onTouchEvent(event);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
      super.onMeasure(MeasureSpec.makeMeasureSpec(WonActivity.W.getWidth() - 2, MeasureSpec.EXACTLY),
          MeasureSpec.makeMeasureSpec(WonActivity.W.getHeight(), MeasureSpec.EXACTLY));
      setBackgroundColor(Color.TRANSPARENT);
      setBackgroundDrawable(WonDraw.W.getWood());
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
      super.onDraw(canvas);
      if (pd == null) return;

      canvas.save();
      pd.draw(canvas, handView.hand, true);
      canvas.restore();
    }

    public void onClick(View v)
    {
      switch (v.getId() - BUT_VIEW_ID)
      {
        case BUT_BIRD:
          WonActivity.W.switchToBird(player.id);
          break;

        case BUT_SCORE:
          WonActivity.W.showScoreDlg();
          break;

        case BUT_ROUND:
          WonActivity.W.showRoundDlg();
          break;

        case BUT_MOVE:
          break;
      }
    }
  };

  // custom adapter for the gallery: provides circular functionality
  private class PGAdapter extends BaseAdapter
  {
    public int getCount()
    {
      return Integer.MAX_VALUE;
    }

    public Object getItem(int position)
    {
      return position;
    }

    public long getItemId(int position)
    {
      return position;
    }

    public View getView(int position, View convertView, ViewGroup parent)
    {
      return views[position % views.length];
    }
  };

  public PlayerGallery()
  {
    super(WonActivity.W.getApplicationContext());
    setSpacing(0);
    setBackgroundColor(Color.TRANSPARENT);

    views = new PlayerView[Table.T.getPlayerCount()];

    for (int i = 0; i < Table.T.getPlayerCount(); ++i)
      views[i] = new PlayerView(Table.T.getPlayer(i));

    setAdapter(new PGAdapter());
    setHorizontalFadingEdgeEnabled(false);
    setVerticalFadingEdgeEnabled(false);
  }

  // reset for the next player
  void changeMovingPlayer()
  {
    for (int i = 0; i < views.length; ++i)
      views[i].reset(i == WonActivity.W.getCurrentPlayerID());
    setViewedPlayer(Math.max(WonActivity.W.getCurrentPlayerID(), 0));
  }

  // set the player whose buildings to view
  void setViewedPlayer(int index)
  {
    int pos = Integer.MAX_VALUE / 2;
    pos -= pos % views.length;
    setSelection(pos + index);
    views[index].requestFocus();
    views[index].invalidate();
  }

  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
  {
    int kEvent = e2.getX() > e1.getX() ?
      KeyEvent.KEYCODE_DPAD_LEFT :
      KeyEvent.KEYCODE_DPAD_RIGHT;
    onKeyDown(kEvent, null);

    return true;
  }

  @Override
  public boolean onTouchEvent(MotionEvent event)
  {
    boolean b = super.onTouchEvent(event);

    switch (event.getAction())
    {
      case MotionEvent.ACTION_DOWN:
        return true;

      case MotionEvent.ACTION_UP:
        if (event.getEventTime() - event.getDownTime() < WonActivity.CLICK_MS)
        {
          if (clickedCard != null)
            WonActivity.W.showCardDlg(clickedCard);
          else if (clickedWonderPlayer != null)
            WonActivity.W.showWonderDlg(clickedWonderPlayer);
        }

        clickedCard = null;
        clickedWonderPlayer = null;
        break;
    }

    return b;
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
  {
    int w = MeasureSpec.getSize(widthMeasureSpec);
    int h = MeasureSpec.getSize(heightMeasureSpec);

    WonActivity.W.resize(w, h);
    super.onMeasure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
        MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
  }
}
4

0 に答える 0