diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..30aa626
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index a29c688..5230380 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,12 +1,11 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.3"
+ compileSdkVersion 26
defaultConfig {
applicationId "com.donkingliang.labelsviewdemo"
- minSdkVersion 9
- targetSdkVersion 25
+ minSdkVersion 14
+ targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -20,12 +19,12 @@ android {
}
dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
- compile 'com.android.support:appcompat-v7:25.3.1'
- testCompile 'junit:junit:4.12'
+ implementation 'com.android.support:appcompat-v7:26.1.0'
+ testImplementation 'junit:junit:4.12'
- compile project(":labels")
+ implementation project(":labels")
}
diff --git a/app/src/main/java/com/donkingliang/labelsviewdemo/MainActivity.java b/app/src/main/java/com/donkingliang/labelsviewdemo/MainActivity.java
index b8ca985..270dfa3 100644
--- a/app/src/main/java/com/donkingliang/labelsviewdemo/MainActivity.java
+++ b/app/src/main/java/com/donkingliang/labelsviewdemo/MainActivity.java
@@ -14,16 +14,32 @@
import static com.donkingliang.labelsviewdemo.R.id.labels;
-public class MainActivity extends AppCompatActivity implements View.OnClickListener {
+public class MainActivity extends AppCompatActivity implements LabelsView.OnLabelClickListener {
+ private LabelsView btnLabels;
private LabelsView labelsView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
-
- labelsView = (LabelsView) findViewById(labels);
+ btnLabels = findViewById(R.id.btnLabels);
+ labelsView = findViewById(labels);
+
+ // 按钮组
+ ArrayList btns = new ArrayList<>();
+ btns.add("不可选中");
+ btns.add("单选(可反选)");
+ btns.add("单选(不可反选)");
+ btns.add("多选");
+ btns.add("多选(最多5个)");
+ btns.add("多选(最少1个)");
+ btns.add("多选(1,2必选)");
+ btns.add("指示器模式");
+ btns.add("取消选中");
+ btns.add("点击");
+ btnLabels.setLabels(btns);
+ btnLabels.setOnLabelClickListener(this);
//测试的数据
// ArrayList label = new ArrayList<>();
@@ -54,66 +70,6 @@ protected void onCreate(Bundle savedInstanceState) {
testList.add(new TestBean("PHP", 10));
testList.add(new TestBean("Python", 11));
testList.add(new TestBean("Swift", 12));
- testList.add(new TestBean("Android", 1));
- testList.add(new TestBean("IOS", 2));
- testList.add(new TestBean("前端", 3));
- testList.add(new TestBean("后台", 4));
- testList.add(new TestBean("微信开发", 5));
- testList.add(new TestBean("游戏开发", 6));
- testList.add(new TestBean("Java", 7));
- testList.add(new TestBean("JavaScript", 8));
- testList.add(new TestBean("C++", 9));
- testList.add(new TestBean("PHP", 10));
- testList.add(new TestBean("Python", 11));
- testList.add(new TestBean("Swift", 12));
- testList.add(new TestBean("Android", 1));
- testList.add(new TestBean("IOS", 2));
- testList.add(new TestBean("前端", 3));
- testList.add(new TestBean("后台", 4));
- testList.add(new TestBean("微信开发", 5));
- testList.add(new TestBean("游戏开发", 6));
- testList.add(new TestBean("Java", 7));
- testList.add(new TestBean("JavaScript", 8));
- testList.add(new TestBean("C++", 9));
- testList.add(new TestBean("PHP", 10));
- testList.add(new TestBean("Python", 11));
- testList.add(new TestBean("Swift", 12));
- testList.add(new TestBean("Android", 1));
- testList.add(new TestBean("IOS", 2));
- testList.add(new TestBean("前端", 3));
- testList.add(new TestBean("后台", 4));
- testList.add(new TestBean("微信开发", 5));
- testList.add(new TestBean("游戏开发", 6));
- testList.add(new TestBean("Java", 7));
- testList.add(new TestBean("JavaScript", 8));
- testList.add(new TestBean("C++", 9));
- testList.add(new TestBean("PHP", 10));
- testList.add(new TestBean("Python", 11));
- testList.add(new TestBean("Swift", 12));
- testList.add(new TestBean("Android", 1));
- testList.add(new TestBean("IOS", 2));
- testList.add(new TestBean("前端", 3));
- testList.add(new TestBean("后台", 4));
- testList.add(new TestBean("微信开发", 5));
- testList.add(new TestBean("游戏开发", 6));
- testList.add(new TestBean("Java", 7));
- testList.add(new TestBean("JavaScript", 8));
- testList.add(new TestBean("C++", 9));
- testList.add(new TestBean("PHP", 10));
- testList.add(new TestBean("Python", 11));
- testList.add(new TestBean("Swift", 12));
- testList.add(new TestBean("Android", 1));
- testList.add(new TestBean("IOS", 2));
- testList.add(new TestBean("前端", 3));
- testList.add(new TestBean("后台", 4));
- testList.add(new TestBean("微信开发", 5));
- testList.add(new TestBean("游戏开发", 6));
- testList.add(new TestBean("Java", 7));
- testList.add(new TestBean("JavaScript", 8));
- testList.add(new TestBean("C++", 9));
- testList.add(new TestBean("PHP", 10));
- testList.add(new TestBean("Python", 11));
- testList.add(new TestBean("Swift", 12));
labelsView.setLabels(testList, new LabelsView.LabelTextProvider() {
@Override
@@ -126,75 +82,66 @@ public CharSequence getLabelText(TextView label, int position, TestBean data) {
// labelsView.setMaxLines(1);
labelsView.clearAllSelect();
-
- findViewById(R.id.btn_none).setOnClickListener(this);
- findViewById(R.id.btn_single).setOnClickListener(this);
- findViewById(R.id.btn_multi).setOnClickListener(this);
- findViewById(R.id.btn_multi_5).setOnClickListener(this);
- findViewById(R.id.btn_un_select).setOnClickListener(this);
- findViewById(R.id.btn_click).setOnClickListener(this);
- findViewById(R.id.btn_single_irrevocably).setOnClickListener(this);
- findViewById(R.id.btn_multi_compulsory).setOnClickListener(this);
- findViewById(R.id.btn_multi_1).setOnClickListener(this);
- findViewById(R.id.btn_indicator).setOnClickListener(this);
}
@Override
- public void onClick(View v) {
+ public void onLabelClick(TextView label, Object data, int position) {
labelsView.setOnLabelClickListener(null);
- switch (v.getId()) {
- case R.id.btn_none:
+ labelsView.clearCompulsorys();
+ switch (position) {
+ case 0:
labelsView.setSelectType(LabelsView.SelectType.NONE);
break;
- case R.id.btn_single:
+ case 1:
labelsView.setSelectType(LabelsView.SelectType.SINGLE);
break;
- case R.id.btn_single_irrevocably:
+ case 2:
labelsView.setSelectType(LabelsView.SelectType.SINGLE_IRREVOCABLY);
break;
- case R.id.btn_multi:
+ case 3:
labelsView.setSelectType(LabelsView.SelectType.MULTI);
labelsView.setMaxSelect(0);
labelsView.setMinSelect(0);
break;
- case R.id.btn_multi_5:
+ case 4:
labelsView.setSelectType(LabelsView.SelectType.MULTI);
labelsView.setMaxSelect(5);
labelsView.setMinSelect(0);
break;
- case R.id.btn_multi_1:
+ case 5:
labelsView.setSelectType(LabelsView.SelectType.MULTI);
labelsView.setMaxSelect(0);
labelsView.setMinSelect(1);
break;
- case R.id.btn_multi_compulsory:
+ case 6:
labelsView.setSelectType(LabelsView.SelectType.MULTI);
labelsView.setMaxSelect(0);
labelsView.setMinSelect(0);
labelsView.setCompulsorys(0, 1);
break;
- case R.id.btn_indicator:
-
+ case 7:
labelsView.setIndicator(!labelsView.isIndicator());
if (labelsView.isIndicator()) {
- ((TextView) v).setText("取消指示器模式");
+ btnLabels.getLabels().set(position, "取消指示器模式");
+ label.setText("取消指示器模式");
} else {
- ((TextView) v).setText("指示器模式");
+ btnLabels.getLabels().set(position, "指示器模式");
+ label.setText("指示器模式");
}
break;
- case R.id.btn_un_select:
+ case 8:
labelsView.clearAllSelect();
break;
- case R.id.btn_click:
+ case 9:
labelsView.setSelectType(LabelsView.SelectType.NONE);
labelsView.setOnLabelClickListener(new LabelsView.OnLabelClickListener() {
@Override
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index c87295c..47a4c9f 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -6,126 +6,45 @@
android:background="#cccccc"
android:orientation="vertical">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:minHeight="25dp"
+ android:padding="5dp"
+ app:labelBackground="@drawable/label_bg"
+ app:labelTextColor="@drawable/label_text_color"
+ app:labelTextHeight="wrap_content"
+ app:labelTextPaddingBottom="5dp"
+ app:labelTextPaddingLeft="10dp"
+ app:labelTextPaddingRight="10dp"
+ app:labelTextPaddingTop="5dp"
+ app:labelTextSize="14sp"
+ app:labelTextWidth="wrap_content"
+ app:lineMargin="10dp"
+ app:maxSelect="0"
+ app:minSelect="1"
+ app:selectType="MULTI"
+ app:wordMargin="10dp" />
diff --git a/build.gradle b/build.gradle
index d0aa704..f6f90b2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,9 +3,10 @@
buildscript {
repositories {
jcenter()
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.2'
+ classpath 'com.android.tools.build:gradle:3.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -15,6 +16,7 @@ buildscript {
allprojects {
repositories {
jcenter()
+ google()
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 9a778d6..1be472a 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Mon Dec 28 10:00:20 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
diff --git a/labels/build.gradle b/labels/build.gradle
index 77e1222..dd45ce5 100644
--- a/labels/build.gradle
+++ b/labels/build.gradle
@@ -3,12 +3,10 @@ apply plugin: 'com.android.library'
group='com.github.donkingliang' // 指定group,com.github.<用户名>
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.3"
-
+ compileSdkVersion 26
defaultConfig {
- minSdkVersion 9
- targetSdkVersion 25
+ minSdkVersion 14
+ targetSdkVersion 26
versionCode 1
versionName "1.0"
}
@@ -21,9 +19,8 @@ android {
}
dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- testCompile 'junit:junit:4.12'
- compile 'com.android.support:appcompat-v7:25.3.1'
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ testImplementation 'junit:junit:4.12'
}
//---------------------------------------------
diff --git a/labels/src/main/java/com/donkingliang/labels/LabelsView.java b/labels/src/main/java/com/donkingliang/labels/LabelsView.java
index c1c8859..166fdb1 100644
--- a/labels/src/main/java/com/donkingliang/labels/LabelsView.java
+++ b/labels/src/main/java/com/donkingliang/labels/LabelsView.java
@@ -9,12 +9,10 @@
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
@@ -40,6 +38,7 @@ public class LabelsView extends ViewGroup implements View.OnClickListener {
private int mMaxSelect;
private int mMinSelect;
private int mMaxLines;
+ private boolean isSingleLine = false;
private boolean isIndicator; //只能看,不能手动改变选中状态。
@@ -164,6 +163,8 @@ private void getAttrs(Context context, AttributeSet attrs) {
mLabelBg = getResources().getDrawable(R.drawable.default_label_bg);
}
+ isSingleLine = mTypedArray.getBoolean(R.styleable.labels_view_singleLine, false);
+
mTypedArray.recycle();
}
}
@@ -188,6 +189,44 @@ private void showEditPreview() {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (isSingleLine) {
+ measureSingleLine(widthMeasureSpec, heightMeasureSpec);
+ } else {
+ measureMultiLine(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ /**
+ * 测量单行模式
+ *
+ * @param widthMeasureSpec
+ * @param heightMeasureSpec
+ */
+ private void measureSingleLine(int widthMeasureSpec, int heightMeasureSpec) {
+ int count = getChildCount();
+ int contentWidth = 0; //记录内容的宽度
+ int maxItemHeight = 0; //记录一行中item高度最大的高度
+
+ for (int i = 0; i < count; i++) {
+ View view = getChildAt(i);
+ measureChild(view, widthMeasureSpec, heightMeasureSpec);
+ contentWidth += view.getMeasuredWidth();
+ if (i != count - 1) {
+ contentWidth += mWordMargin;
+ }
+ maxItemHeight = Math.max(maxItemHeight, view.getMeasuredHeight());
+ }
+ setMeasuredDimension(measureSize(widthMeasureSpec, contentWidth + getPaddingLeft() + getPaddingRight()),
+ measureSize(heightMeasureSpec, maxItemHeight + getPaddingTop() + getPaddingBottom()));
+ }
+
+ /**
+ * 测量多行模式
+ *
+ * @param widthMeasureSpec
+ * @param heightMeasureSpec
+ */
+ private void measureMultiLine(int widthMeasureSpec, int heightMeasureSpec) {
int count = getChildCount();
int maxWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
@@ -237,11 +276,11 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
contentHeight += maxItemHeight;
maxLineWidth = Math.max(maxLineWidth, lineWidth);
- setMeasuredDimension(measureWidth(widthMeasureSpec, maxLineWidth),
- measureHeight(heightMeasureSpec, contentHeight));
+ setMeasuredDimension(measureSize(widthMeasureSpec, maxLineWidth + getPaddingLeft() + getPaddingRight()),
+ measureSize(heightMeasureSpec, contentHeight + getPaddingTop() + getPaddingBottom()));
}
- private int measureWidth(int measureSpec, int contentWidth) {
+ private int measureSize(int measureSpec, int size) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
@@ -249,29 +288,13 @@ private int measureWidth(int measureSpec, int contentWidth) {
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
- result = contentWidth + getPaddingLeft() + getPaddingRight();
+ result = size;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
result = Math.max(result, getSuggestedMinimumWidth());
- return result;
- }
-
- private int measureHeight(int measureSpec, int contentHeight) {
- int result = 0;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
-
- if (specMode == MeasureSpec.EXACTLY) {
- result = specSize;
- } else {
- result = contentHeight + getPaddingTop() + getPaddingBottom();
- if (specMode == MeasureSpec.AT_MOST) {
- result = Math.min(result, specSize);
- }
- }
- result = Math.max(result, getSuggestedMinimumHeight());
+ result = resolveSizeAndState(result, measureSpec, 0);
return result;
}
@@ -288,7 +311,7 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
for (int i = 0; i < count; i++) {
View view = getChildAt(i);
- if (contentWidth < x + view.getMeasuredWidth() + getPaddingRight()) {
+ if (!isSingleLine && contentWidth < x + view.getMeasuredWidth() + getPaddingRight()) {
lineCount++;
if (mMaxLines > 0 && lineCount > mMaxLines) {
break;
@@ -327,6 +350,7 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
private static final String KEY_LABEL_WIDTH_STATE = "key_label_width_state";
private static final String KEY_LABEL_HEIGHT_STATE = "key_label_height_state";
private static final String KEY_LABEL_GRAVITY_STATE = "key_label_gravity_state";
+ private static final String KEY_SINGLE_LINE_STATE = "key_single_line_state";
@Override
protected Parcelable onSaveInstanceState() {
@@ -379,6 +403,8 @@ protected Parcelable onSaveInstanceState() {
bundle.putIntegerArrayList(KEY_COMPULSORY_LABELS_STATE, mCompulsorys);
}
+ bundle.putBoolean(KEY_SINGLE_LINE_STATE, isSingleLine);
+
return bundle;
}
@@ -405,7 +431,7 @@ protected void onRestoreInstanceState(Parcelable state) {
mLabelWidth = bundle.getInt(KEY_LABEL_WIDTH_STATE, mLabelWidth);
mLabelHeight = bundle.getInt(KEY_LABEL_HEIGHT_STATE, mLabelHeight);
//恢复标签方向
- mLabelGravity = bundle.getInt(KEY_LABEL_GRAVITY_STATE, mLabelGravity);
+ setLabelGravity(bundle.getInt(KEY_LABEL_GRAVITY_STATE, mLabelGravity));
//恢复标签内边距
int[] padding = bundle.getIntArray(KEY_PADDING_STATE);
if (padding != null && padding.length == 4) {
@@ -426,6 +452,8 @@ protected void onRestoreInstanceState(Parcelable state) {
//恢复是否是指示器模式
setIndicator(bundle.getBoolean(KEY_INDICATOR_STATE, isIndicator));
+ setSingleLine(bundle.getBoolean(KEY_SINGLE_LINE_STATE, isSingleLine));
+
// //恢复标签列表
// ArrayList labels = bundle.getStringArrayList(KEY_LABELS_STATE);
// if (labels != null && !labels.isEmpty()) {
@@ -993,6 +1021,22 @@ public boolean isIndicator() {
return isIndicator;
}
+ /**
+ * 设置单行显示
+ *
+ * @param isSingleLine
+ */
+ public void setSingleLine(boolean isSingleLine) {
+ if (this.isSingleLine != isSingleLine) {
+ this.isSingleLine = isSingleLine;
+ requestLayout();
+ }
+ }
+
+ public boolean isSingleLine() {
+ return isSingleLine;
+ }
+
/**
* 设置标签的点击监听
*
diff --git a/labels/src/main/res/values/attr.xml b/labels/src/main/res/values/attr.xml
index 4bb6819..ba63237 100644
--- a/labels/src/main/res/values/attr.xml
+++ b/labels/src/main/res/values/attr.xml
@@ -69,5 +69,6 @@
+