다른 크기의 셀 하나와 함께 끌어서 놓기 기능으로 gridview를 만들려고했습니다. 나는 그리드 드래그 앤 드랍과 그 잘 작동했다. 당신은 herecolspan 및 rowSpan이있는 GridView
의 코드를 확인하실 수 있습니다하지만 난 들고 뛰기 교체 될 다른 떨어지는 것 같이이처럼 순수하게 동적 싶은
다른 크기의 셀 하나와 함께 끌어서 놓기 기능으로 gridview를 만들려고했습니다. 나는 그리드 드래그 앤 드랍과 그 잘 작동했다. 당신은 herecolspan 및 rowSpan이있는 GridView
의 코드를 확인하실 수 있습니다하지만 난 들고 뛰기 교체 될 다른 떨어지는 것 같이이처럼 순수하게 동적 싶은
셀의 크기 조정을 수용 할 수있는 새로운 코드로 업데이트되었습니다. 귀하의 질문은 GridView
을 의미하지만 제공된 코드는 GridView
을 언급하지 않고 GridLayout
을 대신 사용하므로 GridLayout
이 올바른 레이아웃이라고 가정합니다.
하나의 2x2 타일로 조롱 된 레이아웃을 사용하여 데모를 작성했습니다. 2x2 타일을 수용하기 위해 제공 한 코드를 수정했습니다. 2x2 타일을 구현하기 위해 추가 한 코드 외에도 MainAcitivity에 대한 유일한 변경 사항은 다른 방법으로 (x, y) 위치에서 인덱스를 계산하는 calculateNextIndex
메서드에 대한 것입니다. 레이아웃과 LongPressListener 클래스도 제공되지 않았기 때문에 조롱을당했습니다. 여기
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final int ITEMS = 10;
private GridLayout mGrid;
private ScrollView mScrollView;
private ValueAnimator mAnimator;
private Boolean isScroll = false;
private GridLayout.Spec m1xSpec = GridLayout.spec(GridLayout.UNDEFINED, 1);
private GridLayout.Spec m2xSpec = GridLayout.spec(GridLayout.UNDEFINED, 2);
private int mBaseWidth;
private int mBaseHeight;
private int mBaseMargin;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mScrollView = (ScrollView) findViewById(R.id.scrollView);
mScrollView.setSmoothScrollingEnabled(true);
mGrid = (GridLayout) findViewById(R.id.grid);
mGrid.setOnDragListener(new DragListener());
final LayoutInflater inflater = LayoutInflater.from(this);
GridLayout.LayoutParams lp;
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
float dpiToPx = displayMetrics.density;
View view = inflater.inflate(R.layout.item, mGrid, false);
lp = (GridLayout.LayoutParams) view.getLayoutParams();
mBaseWidth = lp.width;
mBaseHeight = lp.height;
mBaseMargin = lp.rightMargin;
for (int i = 0; i < ITEMS; i++) {
final View itemView = inflater.inflate(R.layout.item, mGrid, false);
final TextView text = (TextView) itemView.findViewById(R.id.text);
text.setText(String.valueOf(i + 1));
itemView.setOnLongClickListener(new LongPressListener());
lp = (i == 0) ? make2x2LayoutParams(itemView) : make1x1LayoutParams(itemView);
mGrid.addView(itemView, lp);
}
}
private GridLayout.LayoutParams make2x2LayoutParams(View view) {
GridLayout.LayoutParams lp = (GridLayout.LayoutParams) view.getLayoutParams();
lp.width = mBaseWidth * 2 + 2 * mBaseMargin;
lp.height = mBaseHeight * 2 + 2 * mBaseMargin;
lp.rowSpec = m2xSpec;
lp.columnSpec = m2xSpec;
lp.setMargins(mBaseMargin, mBaseMargin, mBaseMargin, mBaseMargin);
return lp;
}
private GridLayout.LayoutParams make1x1LayoutParams(View view) {
GridLayout.LayoutParams lp = (GridLayout.LayoutParams) view.getLayoutParams();
lp.width = mBaseWidth;
lp.height = mBaseHeight;
lp.setMargins(mBaseMargin, mBaseMargin, mBaseMargin, mBaseMargin);
lp.rowSpec = m1xSpec;
lp.columnSpec = m1xSpec;
return lp;
}
private int mDraggedIndex;
class DragListener implements View.OnDragListener {
@Override
public boolean onDrag(View v, DragEvent event) {
final View view = (View) event.getLocalState();
int index = calculateNextIndex(event.getX(), event.getY());
View child;
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
mDraggedIndex = index;
break;
case DragEvent.ACTION_DRAG_LOCATION:
if (view == v) return true;
// get the new list index
final Rect rect = new Rect();
mScrollView.getHitRect(rect);
final int scrollY = mScrollView.getScrollY();
if (event.getY() - scrollY > mScrollView.getBottom() - 250) {
startScrolling(scrollY, mGrid.getHeight());
} else if (event.getY() - scrollY < mScrollView.getTop() + 250) {
startScrolling(scrollY, 0);
} else {
stopScrolling();
}
child = mGrid.getChildAt(0);
if (index == 0) {
child.setLayoutParams(make1x1LayoutParams(child));
view.setLayoutParams(make2x2LayoutParams(view));
} else if (mDraggedIndex == 0) {
view.setLayoutParams(make1x1LayoutParams(view));
child.setLayoutParams(make2x2LayoutParams(child));
} else {
child.setLayoutParams(make2x2LayoutParams(child));
view.setLayoutParams(make1x1LayoutParams(view));
}
mGrid.removeView(view);
mGrid.addView(view, index);
break;
case DragEvent.ACTION_DROP:
for (int i = 0; i < mGrid.getChildCount(); i++) {
child = mGrid.getChildAt(i);
child.setLayoutParams(make1x1LayoutParams(child));
}
mGrid.removeView(view);
if (index == 0) {
view.setLayoutParams(make2x2LayoutParams(view));
}
mGrid.addView(view, index);
view.setVisibility(View.VISIBLE);
mGrid.getChildAt(0).setLayoutParams(make2x2LayoutParams(mGrid.getChildAt(0)));
break;
case DragEvent.ACTION_DRAG_ENDED:
if (!event.getResult()) {
view.setVisibility(View.VISIBLE);
}
break;
}
return true;
}
}
private void startScrolling(int from, int to) {
if (from != to && mAnimator == null) {
isScroll = true;
mAnimator = new ValueAnimator();
mAnimator.setInterpolator(new OvershootInterpolator());
mAnimator.setDuration(Math.abs(to - from));
mAnimator.setIntValues(from, to);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mScrollView.smoothScrollTo(0, (int) valueAnimator.getAnimatedValue());
}
});
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
isScroll = false;
mAnimator = null;
}
});
mAnimator.start();
}
}
private void stopScrolling() {
if (mAnimator != null) {
mAnimator.cancel();
}
}
private int calculateNextIndexOld(float x, float y) {
// calculate which column to move to
final float cellWidth = mGrid.getWidth()/mGrid.getColumnCount();
final int column = (int) (x/cellWidth);
final float cellHeight = mGrid.getHeight()/mGrid.getRowCount();
final int row = (int) Math.floor(y/cellHeight);
int index = row * mGrid.getColumnCount() + column;
if (index >= mGrid.getChildCount()) {
index = mGrid.getChildCount() - 1;
}
Log.d("MainActivity", "<<<<index=" + index);
return index;
}
private int calculateNextIndex(float x, float y) {
// calculate which column to move to
int index;
for (index = 0; index < mGrid.getChildCount(); index++) {
View child = mGrid.getChildAt(index);
Rect rect = new Rect();
child.getHitRect(rect);
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
break;
}
}
if (index >= mGrid.getChildCount()) {
// Move into empty cell? Calculate based upon uniform cell sizes.
index = calculateNextIndexOld(x, y);
}
if (index >= mGrid.getChildCount()) {
// Can't determine where to put it? Add it to the end.
index = mGrid.getChildCount() - 1;
}
return index;
}
}
당신이 데모와 함께 조금 작업하는 경우, 당신은 그것이 가능하다는 것을 볼 수 있습니다 1x1 타일 간격이 열리도록 타일을 이동시킵니다. 이 작업은 정상적으로 수행 될 수 있지만 그렇지 않은 경우 코드를 약간 수정해야 할 수 있습니다.
엇갈림 눈금 레이아웃을 살펴보십시오. 또한 리사이클 러 뷰를 사용할 수있는 경우 [this] (https://stackoverflow.com/questions/29457712/how-to-set-different-columns-for-rows-in-android-gridview)와 같은 것이 도움이 될 수 있습니다. –
내 코드에는 UI 만 있으면 드래그 앤 드롭 기능이 있습니다. https://github.com/felipecsl/AsymmetricGridView와 같은 많은 옵션이 있습니다. – Furqan
지식 게시와 관련하여 질문에 답변을 올리려는 경우. – AsifAli72090