[英]How to get selected child in GridLayout similar to GridView
我要實現以下能力:
GridLayout
選擇一個子View
。 GridLayout
還是在視覺層次有父父將取消選擇的子View
如果已經選定。 問題是,當將View.OnLongClickListener
回調注冊到子View
時,單擊它們時,父GridLayout
或任何祖先注冊的回調( View.OnClickListener
或View.onTouchEvent
)都View.OnClickListener
被調用。
如何在與AdapterView.OnItemSelectedListener
或AdapterView.OnItemLongClickListener
相似的GridLayout
獲取選定的子AdapterView.OnItemLongClickListener
並解決上述問題?
將“選定”視圖存儲為全局變量,並在其焦點更改時將其刪除怎么辦? 通過使用focusable
, focusableInTouchMode
和onClick
偵聽器,您可以獲得正確的結果。 我不確定這是否是最好的解決方案,但它是否有效。
您將需要什么:
- 全局View變量 :長時間選中
GridLayout
的子級。- (可選)與任何
ViewGroup
一樣的自定義父容器 :它將在其所有子級[*]上設置可聚焦的偵聽器。 在測試中,我使用了LinearLayout
和RelativeLayout
。
[*]如果您不使用可選的父級自定義類,則必須在父級ViewGroup的所有子級上設置android:focusable="true"
和android:focusableInTouchMode="true"
。 而且,您必須設置OnClickListener
才能在單擊父ViewGroup時調用removeViewSelected()
。
- 為
GridLayout
子級添加Click偵聽器:更新所選視圖。- 實現Focus偵聽器 :如果所選視圖失去焦點,則將其刪除。
它將處理父級和子級層次結構上的所有焦點更改狀態,請參見輸出:
我使用以下模式:
CoordinatorLayout --- simple root group
ParentLayout --- aka "parentlayout"
Button --- simple Button example
GridLayout --- aka "gridlayout"
FloattingActionButton --- simple Button example
讓我們在Activity
准備選定的View
及其更新方法:
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();
}
}
});
然后,可選的自定義ViewGroup
:這是可選的,因為您可以通過XML和clickable
偵聽器動態設置focusable
狀態,但對我來說似乎更容易。 我使用以下自定義Class
作為父容器:
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>
希望這會有用。
使用以下代碼:
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);
}
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.