13

Android 向けの Gmail アプリケーションで使用されている「元に戻すバー」の実装を見つけました。「UndoBar」は、基本的にレイアウトの上に表示されるビューです。

残念ながら、それは完全ではありません。バーの外側の画面に触れてバーを閉じる機能はありません。

FrameLayoutバーの非表示を処理するオーバーライドを実装しましonInterceptTouchEventたが、アクション バーに触れても何もしません。

Action Bar からそのようなイベントを処理する方法はありますか?

以下に、「元に戻すバー」が表示された画像があります。赤い点で表されるアクションバーでタッチを処理するために達成したいこと。

ここに画像の説明を入力

4

8 に答える 8

7

アクティビティの dispatchTouchEvent をオーバーライドしてみてください。

dispatchTouchEvent(MotionEvent event){

     int x= event.getRawX();
     int y= event.getRawY();


         if(/*check bounds of your view*/){
          // set your views visiblity to gone or what you want. 
         }
      //for prevent consuming the event.
      return super().dispatchTouchEvent(event);    
}

アップデート

dispatchTouchEvent(MotionEvent event){

     int x= event.getRawX();
     int y= event.getRawY();

      return super().dispatchTouchEvent(event)||[YourView].onTouch(event);    
}
于 2013-05-13T06:31:05.837 に答える
2

アクティビティの dispatchTouchEvent(ev: MotionEvent) メソッドをオーバーライドするだけです


無期限のスナックバーを閉じるこの例を見てください

class MainActivity : AppCompatActivity() {

private var snackbar: Snackbar? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(toolbar)

    // show indefinite snackbar
    snackbar = Snackbar.make(coordinator_layout, "Hello world!", Snackbar.LENGTH_INDEFINITE).apply {
        show()
    }
}

/**
 * On each touch event:
 * Check is [snackbar] present and displayed
 * and dismiss it if user touched anywhere outside it's bounds
 */
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
    // dismiss shown snackbar if user tapped anywhere outside snackbar
    snackbar?.takeIf { it.isShown }?.run {
        val touchPoint = Point(Math.round(ev.rawX), Math.round(ev.rawY))
        if (!isPointInsideViewBounds(view, touchPoint)) {
            dismiss()
            snackbar = null // set snackbar to null to prevent this block being executed twice
        }
    }

    // call super
    return super.dispatchTouchEvent(ev)
}

/**
 * Defines bounds of displayed view and check is it contains [Point]
 * @param view View to define bounds
 * @param point Point to check inside bounds
 * @return `true` if view bounds contains point, `false` - otherwise
 */
private fun isPointInsideViewBounds(view: View, point: Point): Boolean = Rect().run {
    // get view rectangle
    view.getDrawingRect(this)

    // apply offset
    IntArray(2).also { locationOnScreen ->
        view.getLocationOnScreen(locationOnScreen)
        offset(locationOnScreen[0], locationOnScreen[1])
    }

    // check is rectangle contains point
    contains(point.x, point.y)
}
}        

または、完全な要点を確認してください

于 2018-11-10T23:37:23.987 に答える
0

考えられる解決策は 2 つあります。

コメントで述べたように、スクロールリスナーを実装して、わずかなスクロールListViewで簡単に呼び出すことができます。hideUndoBar(true)

また

を変更できますUndoBarController。元に戻すバーは、コンストラクターとビューへの show メソッド setFocus でリスナーをView平手打ちしただけであることがわかります。OnFocusChangeView

ビューがフォーカスを失ったかどうかをOnFocusChange確認し、 を呼び出しますhideUndoBar(true)

アップデート

ここに Gist を作成しましたhttps://gist.github.com/atgheb/5551961UndoBarControllerを変更して、フォーカスを失ったときに非表示になる機能を追加する 方法を示しています。

私はそれをテストしていませんが、なぜうまくいかないのかわかりません。

于 2013-05-10T01:58:02.553 に答える
0

onTouchEventFrameLayout で を試しましたか?

私はそれを試したことはありませんが、MotionEventそのレイアウトACTION_OUTSIDEアクションが発生する必要がある場合、それは理にかなっていると思います。

以下を試してください。

public boolean onTouchEvent(MotionEvent event)  
{  

       if(event.getAction() == MotionEvent.ACTION_OUTSIDE){  

             undoBar.setVisibility(View.GONE);
       }  
       return true;  
}  
于 2013-05-09T15:01:58.940 に答える
0
params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSPARENT);

実際に必要なものは次のとおりです。

WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH

ドキュメントには次のように記載されています。

ウィンドウ フラグ: FLAG_NOT_TOUCH_MODAL を設定した場合、このフラグを設定して、ウィンドウの外で発生したタッチに対してアクション MotionEvent.ACTION_OUTSIDE を持つ単一の特別な MotionEvent を受け取ることができます。

于 2014-02-05T04:02:52.723 に答える
-2

Activity以下のコードを使用して、すべてのタッチ イベントを取得できます。このコードも同様に影響を受けると思いActionBarます。

public class MainActivity extends Activity {
...
// This example shows an Activity, but you would use the same approach if
// you were subclassing a View.
@Override
public boolean onTouchEvent(MotionEvent event){ 

    int action = MotionEventCompat.getActionMasked(event);

    switch(action) {
        case (MotionEvent.ACTION_DOWN) :
            Log.d(DEBUG_TAG,"Action was DOWN");
            return true;
        case (MotionEvent.ACTION_MOVE) :
            Log.d(DEBUG_TAG,"Action was MOVE");
            return true;
        case (MotionEvent.ACTION_UP) :
            Log.d(DEBUG_TAG,"Action was UP");
            return true;
        case (MotionEvent.ACTION_CANCEL) :
            Log.d(DEBUG_TAG,"Action was CANCEL");
            return true;
        case (MotionEvent.ACTION_OUTSIDE) :
            Log.d(DEBUG_TAG,"Movement occurred outside bounds " +
                    "of current screen element");
            return true;      
        default : 
            return super.onTouchEvent(event);
    }      
}
于 2013-04-22T20:26:23.973 に答える