1

私は次の能力を達成したいと考えています。

  • 長い間クリックして、毎回View内の子を 1 つだけ選択します。GridLayout
  • GridLayoutビジュアル階層内の またはいずれかの祖先の親をクリックすると、選択された子Viewが既に選択されている場合、選択が解除されます。

View.OnLongClickListener問題は、 child へのコールバックを登録するときにView、親GridLayoutも先祖も登録されたコールバック (View.OnClickListenerまたはView.onTouchEvent) をクリックしたときに呼び出されない場合です。

上記の問題を解決するには、選択した子をどちらかにGridLayout似たものにするか、または解決するにはどうすればよいですか?AdapterView.OnItemSelectedListenerAdapterView.OnItemLongClickListener

4

2 に答える 2

4

「選択された」ビューをグローバル変数として保存し、フォーカスが変更されたときにそれを削除するのはどうですか? focusablefocusableInTouchModeおよびonClickリスナーをいじることで、適切な結果が得られる可能性があります。それが最善の解決策かどうかはわかりませんが、うまくいきます。

必要なもの:

  • グローバル ビュー変数:GridLayoutの子が選択された状態で長押しされました。
  • (オプション) any としてのカスタム親コンテナー: すべての子[*]ViewGroupにフォーカス可能なリスナーを設定します。私のテストでは、 aと aを使用しました。LinearLayoutRelativeLayout

[*] オプションの親カスタム クラスを使用しない場合は、親 ViewGroup のすべての子に対して設定する必要がandroid:focusable="true"あります。また、親の ViewGroup がクリックされたときに呼び出すためandroid:focusableInTouchMode="true"に設定する必要があります。OnClickListenerremoveViewSelected()

  • 子のクリック リスナーの追加GridLayout: 選択したビューを更新します。
  • フォーカス リスナーの実装: フォーカスが失われている場合、選択したビューを削除します。

親階層と子階層のすべてのフォーカス変更状態を処理します。出力を参照してください。

GridLayout 選択ビューとクリック リスナーのビューの無効化

次のパターンを使用しました。

CoordinatorLayout         --- simple root group
    ParentLayout          --- aka "parentlayout"
        Button            --- simple Button example
        GridLayout        --- aka "gridlayout"
    FloattingActionButton --- simple Button example

Viewで選択したメソッドとその更新メソッドを準備しましょうActivity

private View selectedView;

...
private void setViewSelected(View view) {
    removeViewSelected();

    selectedView = view;
    if (selectedView != null) {
        // change to a selected background for example
        selectedView.setBackgroundColor(
                ContextCompat.getColor(this, R.color.colorAccent));
    }
}

private View getViewSelected() {
    if (selectedView != null) {
        return selectedView;
    }
    return null;
}

private void removeViewSelected() {
    if (selectedView != null) {
        // reset the original background for example
        selectedView.setBackgroundResource(R.drawable.white_with_borders);
        selectedView = null;
    }
    // clear and reset the focus on the parent
    parentlayout.clearFocus();
    parentlayout.requestFocus();
}

GridLayout子ごとに、ClickおよびLongClickリスナーを追加して、選択したビューを更新または削除します。私TextViewのものは動的に追加されましたが、for ループを簡単に作成して子を取得できます。

TextView tv = new TextView(this);
...
gridlayout.addView(tv);

tv.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        removeViewSelected();
    }
});

tv.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View view) {
        setViewSelected(view);
        return true;
    }
});

FocusChange親コンテナにリスナーを設定します。

parentlayout.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View view, boolean hasFocus) {
        View viewSelected = getViewSelected();
        // if the selected view exists and it lost focus
        if (viewSelected != null && !viewSelected.hasFocus()) {
            // remove it
            removeViewSelected();
        }
    }
});

次に、オプションの custom : XML とリスナーによって状態を動的にViewGroup設定できるためオプションですが、私には簡単に思えます。この次のカスタムを親コンテナーとして 使用しました。focusableclickableClass

public class ParentLayout extends RelativeLayout implements View.OnClickListener {

    public ParentLayout(Context context) {
        super(context);
        init();
    }

    public ParentLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ParentLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    // handle focus and click states
    public void init() {
        setFocusable(true);
        setFocusableInTouchMode(true);
        setOnClickListener(this);
    }

    // when positioning all children within this 
    // layout, add their focusable state
    @Override
    protected void onLayout(boolean c, int l, int t, int r, int b) {
        super.onLayout(c, l, t, r, b);

        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            child.setFocusable(true);
            child.setFocusableInTouchMode(true);
        }
        // now, even the Button has a focusable state
    }

    // handle the click events
    @Override
    public void onClick(View view) {
        // clear and set the focus on this viewgroup
        this.clearFocus();
        this.requestFocus();
        // now, the focus listener in Activity will handle
        // the focus change state when this layout is clicked
    }
}

たとえば、これは私が使用したレイアウトです。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout ...>

    <com.app.ParentLayout
        android:id="@+id/parent_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal">

        <Button
            android:id="@+id/sample_button"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_alignParentBottom="true"
            android:text="A Simple Button"
            android:layout_marginTop="20dp"
            android:layout_marginBottom="20dp"/>

        <android.support.v7.widget.GridLayout
            android:id="@+id/grid_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerHorizontal="true"
            android:layout_above="@id/sample_button" .../>
    </com.app.ParentLayout>

    <android.support.design.widget.FloatingActionButton .../>
</android.support.design.widget.CoordinatorLayout>

これが役立つことを願っています。

于 2016-12-28T16:26:09.900 に答える
0

次のコードを使用します。

int last_pos = -1;
GridLayout gridLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    gridLayout = (GridLayout) findViewById(R.id.gridLayout);
    int child_count = gridLayout.getChildCount();
    for(int i =0;i<child_count;i++){
        gridLayout.getChildAt(i).setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                //Deselect previous
                if(last_pos!=-1) gridLayout.getChildAt(last_pos).setSelected(false);
                //Select the one you clicked
                view.setSelected(true);
                last_pos = gridLayout.indexOfChild(view);
                return false;
            }
        });
    }
    //Remove focus if the parent is clicked
    gridLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            gridLayout.getChildAt(last_pos).setSelected(false);
        }
    });
于 2016-12-28T16:20:13.170 に答える