├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── GIF.gif ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── cm │ │ └── channlemanagerview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── cm │ │ │ └── channlemanagerview │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable │ │ └── custom_channel_item_bg.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── cm │ └── channlemanagerview │ └── ExampleUnitTest.java ├── build.gradle ├── channeltagviewLib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── zhl │ │ │ └── channeltagview │ │ │ ├── adapter │ │ │ ├── GroupedGridLayoutManager.java │ │ │ └── GroupedListAdapter.java │ │ │ ├── bean │ │ │ ├── ChannelItem.java │ │ │ └── GroupItem.java │ │ │ ├── listener │ │ │ ├── OnChannelItemClicklistener.java │ │ │ └── UserActionListener.java │ │ │ ├── util │ │ │ └── MeasureUtil.java │ │ │ └── view │ │ │ ├── ChannelTagView.java │ │ │ ├── FloatItemView.java │ │ │ └── FloatItemViewManager.java │ └── res │ │ ├── drawable │ │ ├── channel_item_bg.xml │ │ ├── channel_item_draging.xml │ │ ├── error_drawable_circle.xml │ │ ├── error_inside.xml │ │ └── fixed_item_bg.xml │ │ ├── layout │ │ ├── channel_tag_layout.xml │ │ ├── float_item_view.xml │ │ ├── item_channel_view.xml │ │ └── item_mulite_banner.xml │ │ └── values │ │ ├── attr.xml │ │ ├── colors.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── zhl │ └── channeltagview │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── show.mp4 └── show_category.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /GIF.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/ChannelTagView/d55e95e0e8c4f77ad2b68a42c0234a2d4bdb454a/GIF.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![](https://jitpack.io/v/yilylong/ChannelTagView.svg)](https://jitpack.io/#yilylong/ChannelTagView) 2 | # ChannelTagView 3 | 4 | 一个频道管理view,可拖拽排序,滑动删除。 5 | ---- 6 | 7 | 8 | 9 | 使用 10 | -- 11 | step1.Add it in your root build.gradle at the end of repositories: 12 | - 13 | 14 | allprojects { 15 | repositories { 16 | ... 17 | maven { url 'https://www.jitpack.io' } 18 | } 19 | } 20 | 21 | stpe2.Add the dependency: 22 | - 23 | dependencies { 24 | compile 'com.github.yilylong:ChannelTagView:v1.0.1' 25 | } 26 | 27 | 28 | xml中直接引用: 29 | 30 | 37 | 38 | 39 | 调用 ChannelTagView的initChannels() 方法填充数据即可。有针对里面的item修改的各种属性,针对点击事件和用户的拖动滑动事件接口监听。 40 | 4.4一下可能需要权限,详情查看demo 41 | 42 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | defaultConfig { 7 | applicationId "com.cm.channlemanagerview" 8 | minSdkVersion 15 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support:appcompat-v7:25.3.0' 28 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 29 | testCompile 'junit:junit:4.12' 30 | compile project(':channeltagviewLib') 31 | } 32 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\work\AndroidSDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/cm/channlemanagerview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.cm.channlemanagerview; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.cm.channlemanagerview", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/cm/channlemanagerview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.cm.channlemanagerview; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.View; 6 | import android.widget.Button; 7 | import android.widget.Toast; 8 | 9 | import com.zhl.channeltagview.bean.ChannelItem; 10 | import com.zhl.channeltagview.bean.GroupItem; 11 | import com.zhl.channeltagview.listener.OnChannelItemClicklistener; 12 | import com.zhl.channeltagview.listener.UserActionListener; 13 | import com.zhl.channeltagview.view.ChannelTagView; 14 | 15 | import java.util.ArrayList; 16 | 17 | import cn.bingoogolapple.badgeview.BGABadgeTextView; 18 | 19 | public class MainActivity extends AppCompatActivity { 20 | private ChannelTagView channelTagView; 21 | private ArrayList addedChannels = new ArrayList<>(); 22 | private ArrayList unAddedChannels = new ArrayList<>(); 23 | private ArrayList unAddedItems = new ArrayList<>(); 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_main); 29 | channelTagView = (ChannelTagView) findViewById(R.id.channel_tag_view); 30 | initData(); 31 | Button btn = (Button) findViewById(R.id.btn_opencategory); 32 | btn.setOnClickListener(new View.OnClickListener() { 33 | @Override 34 | public void onClick(View view) { 35 | channelTagView.oPenCategory(!channelTagView.isOpenCategory()); 36 | } 37 | }); 38 | Button btnShow = (Button) findViewById(R.id.btn_showdrawableleft); 39 | btnShow.setOnClickListener(new View.OnClickListener() { 40 | @Override 41 | public void onClick(View view) { 42 | channelTagView.showItemDrawableLeft(!channelTagView.isShowItemDrawableLeft()); 43 | } 44 | }); 45 | channelTagView.showPahtAnim(true); 46 | // channelTagView.setItemLeftDrawableLayoutParams(new RelativeLayout.LayoutParams(50,50)); 47 | // channelTagView.showItemDrawableLeft(true); 48 | // channelTagView.setSwipeEnable(false); 49 | // channelTagView.setCategoryItemBg(R.color.content_color); 50 | // channelTagView.setCategoryItemTxColor(ContextCompat.getColor(this,R.color.content_color)); 51 | // channelTagView.setCategoryItemTxSize(18); 52 | // channelTagView.setChannelItemTxColor(Color.BLUE); 53 | // channelTagView.setChannelItemBg(R.drawable.custom_channel_item_bg); 54 | // channelTagView.setCategrayUnAddedBannerTX("更多栏目"); 55 | // channelTagView.setCategoryAddedBannerBg(R.color.content_color); 56 | // channelTagView.setCategoryBannerTXsize(40); 57 | // channelTagView.setCategoryBannerTXColor(Color.argb(255,221,224,98)); 58 | // channelTagView.setColumnVerticalSpace(20); 59 | channelTagView.initChannels(addedChannels, unAddedItems, true, new ChannelTagView.RedDotRemainderListener() { 60 | 61 | @Override 62 | public boolean showAddedChannelBadge(BGABadgeTextView itemView, int position) { 63 | if (addedChannels.get(position).title.equals("直播")) { 64 | return true; 65 | } else { 66 | return false; 67 | } 68 | } 69 | 70 | @Override 71 | public boolean showUnAddedChannelBadge(BGABadgeTextView itemView, int position) { 72 | if (unAddedChannels.get(position).title.equals("数码") || unAddedChannels.get(position).title.equals("科技")) { 73 | return true; 74 | } else { 75 | return false; 76 | } 77 | } 78 | 79 | @Override 80 | public void handleAddedChannelReddot(BGABadgeTextView itemView, int position) { 81 | itemView.showCirclePointBadge(); 82 | } 83 | 84 | @Override 85 | public void handleUnAddedChannelReddot(BGABadgeTextView itemView, int position) { 86 | if (unAddedChannels.get(position).title.equals("科技")) { 87 | itemView.showTextBadge("new"); 88 | } else { 89 | itemView.showCirclePointBadge(); 90 | } 91 | } 92 | 93 | @Override 94 | public void OnDragDismiss(BGABadgeTextView itemView, int position) { 95 | Toast.makeText(MainActivity.this, "拖拽取消红点提示-", Toast.LENGTH_SHORT).show(); 96 | itemView.hiddenBadge(); 97 | } 98 | 99 | }); 100 | // channelTagView.setFixedChannelBg(R.drawable.fixed_item_bg); 101 | // channelTagView.setFixedChannel(0); 102 | // channelTagView.showPahtAnim(true); 103 | channelTagView.setOnChannelItemClicklistener(new OnChannelItemClicklistener() { 104 | 105 | @Override 106 | public void onAddedChannelItemClick(View itemView, int position) { 107 | Toast.makeText(MainActivity.this, "打开-" + addedChannels.get(position).title, Toast.LENGTH_SHORT).show(); 108 | } 109 | 110 | @Override 111 | public void onUnAddedChannelItemClick(View itemView, int position) { 112 | ChannelItem item = unAddedChannels.remove(position); 113 | addedChannels.add(item); 114 | Toast.makeText(MainActivity.this, "添加频道-" + item.title, Toast.LENGTH_SHORT).show(); 115 | } 116 | 117 | @Override 118 | public void onItemDrawableClickListener(View itemView, int position) { 119 | Toast.makeText(MainActivity.this, "删除-" + MainActivity.this.addedChannels.get(position).title, Toast.LENGTH_SHORT).show(); 120 | unAddedChannels.add(addedChannels.remove(position)); 121 | } 122 | }); 123 | channelTagView.setUserActionListener(new UserActionListener() { 124 | @Override 125 | public void onMoved(int fromPos, int toPos, ArrayList checkedChannels) { 126 | Toast.makeText(MainActivity.this, "将-" + addedChannels.get(fromPos).title + " 换到 " + addedChannels.get(toPos).title, Toast.LENGTH_SHORT).show(); 127 | addedChannels.clear(); 128 | addedChannels.addAll(checkedChannels); 129 | } 130 | 131 | @Override 132 | public void onSwiped(int position, View itemView, ArrayList checkedChannels, ArrayList uncheckedChannels) { 133 | Toast.makeText(MainActivity.this, "删除-" + MainActivity.this.addedChannels.remove(position).title, Toast.LENGTH_SHORT).show(); 134 | unAddedChannels.clear(); 135 | unAddedChannels.addAll(uncheckedChannels); 136 | } 137 | }); 138 | } 139 | 140 | private void initData() { 141 | String[] chanles = getResources().getStringArray(R.array.chanles); 142 | for (int i = 0; i < 7; i++) { 143 | ChannelItem item = new ChannelItem(); 144 | item.id = i; 145 | item.title = chanles[i]; 146 | item.category = "头条"; 147 | addedChannels.add(item); 148 | } 149 | GroupItem groupFinance = new GroupItem(); 150 | groupFinance.category = "金融"; 151 | for (int i = 7; i < 9; i++) { 152 | ChannelItem item = new ChannelItem(); 153 | item.id = i; 154 | item.title = chanles[i]; 155 | item.category = "金融"; 156 | unAddedChannels.add(item); 157 | groupFinance.addChanelItem(item); 158 | } 159 | unAddedItems.add(groupFinance); 160 | 161 | GroupItem groupLife = new GroupItem(); 162 | groupLife.category = "生活"; 163 | for (int i = 9; i < 18; i++) { 164 | ChannelItem item = new ChannelItem(); 165 | item.id = i; 166 | item.title = chanles[i]; 167 | item.category = "生活"; 168 | unAddedChannels.add(item); 169 | groupLife.addChanelItem(item); 170 | } 171 | unAddedItems.add(groupLife); 172 | 173 | GroupItem groupEntertainment = new GroupItem(); 174 | groupEntertainment.category = "娱乐"; 175 | for (int i = 18; i < 22; i++) { 176 | ChannelItem item = new ChannelItem(); 177 | item.id = i; 178 | item.title = chanles[i]; 179 | item.category = "娱乐"; 180 | unAddedChannels.add(item); 181 | groupEntertainment.addChanelItem(item); 182 | } 183 | unAddedItems.add(groupEntertainment); 184 | 185 | GroupItem Grouphumanity = new GroupItem(); 186 | Grouphumanity.category = "人文"; 187 | for (int i = 22; i <= 25; i++) { 188 | ChannelItem item = new ChannelItem(); 189 | item.id = i; 190 | item.title = chanles[i]; 191 | item.category = "人文"; 192 | unAddedChannels.add(item); 193 | Grouphumanity.addChanelItem(item); 194 | } 195 | unAddedItems.add(Grouphumanity); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/custom_channel_item_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |