转载请注明出处:https://blog.youkuaiyun.com/suprememjie/article/details/82465323
在项目中,如果有单独的一页来展示分类功能,经常会有一些交互的操作,比如长按拖拽某一个条目来调整位置、点击某一条目从当前列表中删除移入另一列表等。
看效果先:
直接上代码:
public class DragGridLayout extends GridLayout {
private List<String> items;
private int margin = 15;
// 是否可以拖拽
private boolean isCanDrag;
// 记录被拖拽的View
private View dragView;
// 存放所有条目的矩形区域
private List<Rect> rects;
public void setItems(List<String> items) {
this.items = items;
for (int i = 0; i < items.size(); i++) {
addGridItem(items.get(i));
}
}
public void setCanDrag(boolean canDrag) {
isCanDrag = canDrag;
if (isCanDrag) {
setOnDragListener(onDragListener);
}
}
public DragGridLayout(Context context) {
this(context, null);
}
public DragGridLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DragGridLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 给GridLayout添加item
*/
public void addGridItem(String content) {
TextView tv = new TextView(getContext());
tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
tv.setBackgroundResource(R.drawable.item_bg_selector);
tv.setGravity(Gravity.CENTER);
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.width = getResources().getDisplayMetrics().widthPixels / 4 - margin * 2;
params.setMargins(margin, margin, margin, margin);
tv.setLayoutParams(params);
tv.setText(content);
addView(tv);
if (isCanDrag) {
tv.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
dragView = view;
// 产生浮动的阴影效果
// 只有第二个参数有用,其他传空即可
view.startDrag(null, new View.DragShadowBuilder(view), null, 0);
// true 响应长按事件
return true;
}
});
}
// 设置条目的点击事件
tv.setOnClickListener(onClickListener);
}
private OnDragListener onDragListener = new OnDragListener() {
@Override
public boolean onDrag(View view, DragEvent dragEvent) {
switch (dragEvent.getAction()) {
// 按下
case DragEvent.ACTION_DRAG_STARTED:
dragView.setEnabled(false);
initRects();
break;
// 移动
case DragEvent.ACTION_DRAG_LOCATION:
int exchangeIndex = getExchangeIndex(dragEvent);
if (exchangeIndex > -1 && dragView != getChildAt(exchangeIndex)) {
removeView(dragView);
addView(dragView, exchangeIndex);
}
break;
// 弹起
case DragEvent.ACTION_DRAG_ENDED:
dragView.setEnabled(true);
break;
}
// true 响应拖拽事件
return true;
}
};
private void initRects() {
rects = new ArrayList<>();
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
// 创建矩形
Rect rect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
rects.add(rect);
}
}
/**
* 获取要交换的位置下标
*
* @param dragEvent
* @return
*/
private int getExchangeIndex(DragEvent dragEvent) {
for (int i = 0; i < rects.size(); i++) {
Rect rect = rects.get(i);
if (rect.contains((int) dragEvent.getX(), (int) dragEvent.getY())) {
return i;
}
}
return -1;
}
private OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(View view) {
if (onDragItemClickListener != null) {
onDragItemClickListener.onDragItemClick((TextView) view);
}
}
};
//接口
public interface OnDragItemClickListener {
void onDragItemClick(TextView tv);
}
private OnDragItemClickListener onDragItemClickListener;
public void setOnDragItemClickListener(OnDragItemClickListener onDragItemClickListener) {
this.onDragItemClickListener = onDragItemClickListener;
}
}
对于列表中的 item 是否可以拖拽、点击是否移进和移出列表都是可以从外部设置的,所以控件比较灵活。下面看下在 Activity 中的具体调用:
public class MainActivity extends AppCompatActivity {
private DragGridLayout gridLayout1;
private DragGridLayout gridLayout2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridLayout1 = findViewById(R.id.gridLayout1);
gridLayout2 = findViewById(R.id.gridLayout2);
gridLayout1.setCanDrag(true);
List<String> items = new ArrayList<>();
items.add("明星");
items.add("搞笑");
items.add("情感");
items.add("新时代");
items.add("社会");
items.add("电影");
items.add("游戏");
items.add("音乐");
items.add("动漫");
items.add("萌宠");
gridLayout1.setItems(items);
List<String> items2 = new ArrayList<>();
items2.add("汽车");
items2.add("摄影");
items2.add("国际");
items2.add("数码");
items2.add("财经");
items2.add("股市");
items2.add("读书");
gridLayout2.setItems(items2);
gridLayout1.setOnDragItemClickListener(new DragGridLayout.OnDragItemClickListener() {
@Override
public void onDragItemClick(TextView tv) {
gridLayout1.removeView(tv);
gridLayout2.addGridItem(tv.getText().toString());
}
});
gridLayout2.setOnDragItemClickListener(new DragGridLayout.OnDragItemClickListener() {
@Override
public void onDragItemClick(TextView tv) {
gridLayout2.removeView(tv);
gridLayout1.addGridItem(tv.getText().toString());
}
});
}
}