前言
以前总是在CSDN上看各位前辈的精彩博客,从中也学习了很多东西。其实自己也一直想写博客,直到今天终于要踏出这一步了,有点小兴奋,哈哈!不足之处,还请各位同仁不吝赐教,拜谢!!!
话不多说,工作中我们时常会遇到频道管理的需求,不少博客使用GridView实现这一功能,个人喜欢用自定义的GridLayout实现,萝卜白菜各有所爱,嘿嘿。
功能
要实现的功能如上图所示(当然,左边只是一个参考,这里界面不是重点,我们要实现这个功能)
1. 分上下两部分
2.“我的频道”实现了长按拖拽排序功能;同时,点击某一子条目时,将该条目从“我的频道”中删除,添加到“更多频道”中。
3.“更多频道”实现了点击事件,当点击某一子条目时,该子条目从“更多频道”中删除,添加到“我的频道”中。
实现代码
主程序代码:
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.TextView; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private DragGridLayout showGridLayout; private DragGridLayout hideGridLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initCustom(); } private void initCustom() { showGridLayout = (DragGridLayout) findViewById(R.id.dgl_main_show); showGridLayout.setResource(R.drawable.selector_textbg, 10, 5); showGridLayout.setEnableDrag(true); List<String> items = new ArrayList<>(); items.add("推荐"); items.add("本地事"); items.add("本地人"); items.add("社区"); items.add("图集"); items.add("要闻"); items.add("热点"); items.add("旅游"); items.add("健康"); showGridLayout.setItems(items); hideGridLayout = (DragGridLayout) findViewById(R.id.dgl_main_bottom); hideGridLayout.setEnableDrag(false); hideGridLayout.setResource(R.drawable.selector_textbg, 10, 5); List<String> items1 = new ArrayList<>(); items1.add("家居"); items1.add("奇石"); items1.add("螺蛳粉"); items1.add("情感"); items1.add("文化"); items1.add("体育"); items1.add("汽车"); items1.add("本地号"); items1.add("爆料"); items1.add("时政"); items1.add("美女"); items1.add("公益"); items1.add("公民榜样"); items1.add("亲子"); items1.add("社会"); items1.add("舌尖柳州"); items1.add("开心一刻"); items1.add("居柳州"); hideGridLayout.setItems(items1); //设置点击事件 showGridLayout.setOnItemClickListener(new DragGridLayout.OnItemClickListener() { @Override public void onItemClick(TextView tv) { //当点击时,将返回的TextView从showGridLayout容器中删除,在添加到hideGridLayout中 showGridLayout.removeView(tv); hideGridLayout.addItem(tv.getText().toString()); } }); hideGridLayout.setOnItemClickListener(new DragGridLayout.OnItemClickListener() { @Override public void onItemClick(TextView tv) { hideGridLayout.removeView(tv); showGridLayout.addItem(tv.getText().toString()); } }); } }
布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPry" android:text="点击增删频道,长按拖拽排序"/> <com.example.customview.DragGridLayout android:id="@+id/dgl_main_show" android:layout_width="match_parent" android:layout_height="wrap_content"> </com.example.customview.DragGridLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPry" android:text="频道管理"/> <com.example.customview.DragGridLayout android:id="@+id/dgl_main_bottom" android:layout_width="match_parent" android:layout_height="wrap_content"> </com.example.customview.DragGridLayout> </LinearLayout> </LinearLayout>自定义GridLayout:
注释比较详细了,直接上代码,其中的一些参数,例如margin和padding,可根据项目需求,具体定制。
import android.animation.LayoutTransition; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.DragEvent; import android.view.Gravity; import android.view.View; import android.widget.GridLayout; import android.widget.TextView; import java.util.List; /** * Created by ZLM on 2017/4/3. */ public class DragGridLayout extends GridLayout { private boolean ableDrag; private Rect[] rects; private View dragView; private OnItemClickListener itemClickListener; //拖拽监听 private View.OnDragListener odl = new View.OnDragListener() { @Override public boolean onDrag(View view, DragEvent dragEvent) { switch (dragEvent.getAction()) { case DragEvent.ACTION_DRAG_STARTED: //当拖拽事件产生时,给每个子控件创建出对应的矩形 initRects(); break; case DragEvent.ACTION_DRAG_LOCATION: //当手指移动时,判断当前进入了哪一个子控件范围内,并返回对应子控件的索引 int touchIndex = getTouchIndex(dragEvent); if (touchIndex > -1 && dragView != null && dragView != DragGridLayout.this.getChildAt(touchIndex)) { //先把拖拽的view从当前位置删除,再添加到touchIndex上 DragGridLayout.this.removeView(dragView); DragGridLayout.this.addView(dragView, touchIndex); } break; case DragEvent.ACTION_DRAG_ENDED: if (dragView != null) { dragView.setEnabled(true); } break; default: break; } return true; } }; //长按监听 private View.OnLongClickListener olcl = new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { //长按事件发生时,即给dragView赋值 dragView = view; //拖拽事件 view.startDrag(null, new View.DragShadowBuilder(view), null, 0); view.setEnabled(false); return false; } }; private int getTouchIndex(DragEvent dragEvent) { for (int i = 0; i < rects.length; i++) { Rect rect = rects[i]; if (rect.contains((int) dragEvent.getX(), (int) dragEvent.getY())) { return i; } } return -1; } //创建子控件对应的矩形 private void initRects() { //给容器中的每一个子控件都新建一个矩形 rects = new Rect[getChildCount()]; for (int i = 0; i < getChildCount(); i++) { View childAt = getChildAt(i); rects[i] = new Rect(childAt.getLeft(), childAt.getTop(), childAt.getRight(), childAt.getBottom()); } } public DragGridLayout(Context context) { this(context, null); } public DragGridLayout(Context context, AttributeSet attrs) { super(context, attrs); setColumnCount(4); setLayoutTransition(new LayoutTransition()); } //定义方法,由外部传递一个栏目的数据集合进来,在这里根据数据集合动态创建表格界面 public void setItems(List<String> items) { for (String item : items) { addItem(item); } } //定义方法,设置是否允许拖拽 public void setEnableDrag(boolean EnableDrag) { ableDrag = EnableDrag; if (ableDrag) { setOnDragListener(odl); } else { setOnDragListener(null); } } //定义接口回调 public interface OnItemClickListener { public void onItemClick(TextView tv); } public void setOnItemClickListener(OnItemClickListener listener) { this.itemClickListener = listener; } public void addItem(String item) { TextView tv = getNewTextView(); tv.setText(item); this.addView(tv); } //定义方法,外部传入子条目的背景资源Id,外边距margin(px),tv内边距padding(px) private final float scale = getContext().getResources().getDisplayMetrics().density; private int resId; private int margin; private int padding; public void setResource(int ResourceId, int margin, int padding) { this.resId = ResourceId; this.margin = (int) (margin * scale + 0.5f); this.padding = (int) (padding * scale + 0.5f); } public TextView getNewTextView() { GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams(); layoutParams.width = getResources().getDisplayMetrics().widthPixels / 4 - 2 * margin; layoutParams.height = GridLayout.LayoutParams.WRAP_CONTENT; layoutParams.setMargins(margin, margin, margin, margin); TextView tv = new TextView(getContext()); tv.setLayoutParams(layoutParams); tv.setGravity(Gravity.CENTER); tv.setBackgroundResource(resId); tv.setPadding(padding, padding, padding, padding); if (ableDrag) { tv.setOnLongClickListener(olcl); } else { tv.setOnLongClickListener(null); } tv.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if (itemClickListener != null) { itemClickListener.onItemClick((TextView) view); } } }); return tv; } }drawable/selector_textbg.xml:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="true" android:drawable="@drawable/shape_textbg_nomal"/> <item android:state_enabled="false" android:drawable="@drawable/shape_textbg_pressed"/> </selector>drawable/shape_textbg_nomal.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:width="1dp" android:color="@color/colorBlack"/> <corners android:radius="@dimen/dp8"/> <solid android:color="@color/colorWhite"/> </shape>drawable/shape_textbg_pressed.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:width="1dp" android:dashWidth="2dp" android:dashGap="3dp" android:color="@color/colorRed"/> <corners android:radius="@dimen/dp8"/> <solid android:color="@color/colorWhite"/> </shape>