diff --git a/.gitignore b/.gitignore index 9c4de58..31df7f6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ .DS_Store /build /captures +/.idea/inspectionProfiles/ +/.idea/smartfox_info.xml + diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 98fbf6d..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -Github-FlowLayout \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 9a8b7e5..96cc43e 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,7 +1,6 @@ - diff --git a/.idea/misc.xml b/.idea/misc.xml index dae7a60..cc72de3 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,8 +1,5 @@ - - - - - - - - - - - - - - + @@ -47,7 +34,7 @@ - 1.7 + 1.8 - - diff --git a/README.md b/README.md index 5e966bf..5b4a0a5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Android Gems](http://www.android-gems.com/badge/hongyangAndroid/FlowLayout.svg?branch=master)](http://www.android-gems.com/lib/hongyangAndroid/FlowLayout) - + # FlowLayout Android流式布局,支持单选、多选等,适合用于产品标签等。 @@ -23,7 +23,7 @@ Android流式布局,支持单选、多选等,适合用于产品标签等。 ```java dependencies { - compile 'com.zhy:flowlayout-lib:1.0.0' + compile 'com.hyman:flowlayout-lib:1.1.2' } ``` @@ -43,7 +43,9 @@ dependencies { 支持属性: `max_select`:-1为不限制选择数量,>=1的数字为控制选择tag的数量 -`auto_select_effect` 是否开启默认的选中效果,即为selector中设置的效果,默认为true;如果设置为false,则无选中效果,需要自己在回调中处理。 + +支持通过state=checked来控制选中和取消,也可以自己在Adapter +的onSelected和unSelected中分别处理显示。 ###设置数据 @@ -61,12 +63,11 @@ mFlowLayout.setAdapter(new TagAdapter(mVals) }); ``` + getView中回调,类似ListView等用法。 ### 对于选中状态 -你还在复杂的写代码设置选中后标签的显示效果么,翔哥说No! - ```java @@ -81,6 +82,22 @@ getView中回调,类似ListView等用法。 设置个background,上面一个状态为android:state_checked,另一个为正常。写写布局文件我都嫌慢,怎么能写一堆代码控制效果,设置改个效果,岂不是没时间dota了。 +也可以不依赖state_checked,在下面的回调中自行设置: + +``` +#Adapter +@Override +public void onSelected(int position, View view) { + super.onSelected(position, view); +} + +@Override +public void unSelected(int position, View view) { + super.unSelected(position, view); +} +``` + + ###事件 ```java diff --git a/build.gradle b/build.gradle index 5cfc154..9cf74fe 100644 --- a/build.gradle +++ b/build.gradle @@ -5,9 +5,8 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.2.3' - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0' - classpath 'com.github.dcendents:android-maven-plugin:1.2' + classpath 'com.android.tools.build:gradle:2.2.0' + classpath 'com.novoda:bintray-release:0.3.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/flowlayout-lib/build.gradle b/flowlayout-lib/build.gradle index 445c824..31ef8a6 100644 --- a/flowlayout-lib/build.gradle +++ b/flowlayout-lib/build.gradle @@ -1,15 +1,13 @@ apply plugin: 'com.android.library' -apply plugin: 'com.github.dcendents.android-maven' -apply plugin: 'com.jfrog.bintray' +apply plugin: 'com.novoda.bintray-release' -version = "1.0.0" android { - compileSdkVersion 22 - buildToolsVersion "23.0.0 rc3" + compileSdkVersion 25 + buildToolsVersion "25.0.3" defaultConfig { minSdkVersion 10 - targetSdkVersion 22 + targetSdkVersion 25 versionCode 1 versionName "1.0" } @@ -22,79 +20,15 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:22.2.1' + compile fileTree(include: ['*.jar'], dir: 'libs') + compile 'com.android.support:support-v4:25.0.0' } -def siteUrl = 'https://github.com/hongyangAndroid/FlowLayout' // #CONFIG# // project homepage -def gitUrl = 'https://github.com/hongyangAndroid/FlowLayout.git' // #CONFIG# // project git -group = "com.zhy" - -install { - repositories.mavenInstaller { - // This generates POM.xml with proper parameters - pom { - project { - packaging 'aar' - name 'flowlayout' // #CONFIG# // project title - url siteUrl - // Set your license - licenses { - license { - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - } - } - developers { - developer { - id 'hongyangAndroid' // #CONFIG# // your user id (you can write your nickname) - name 'ZhangHongyang' // #CONFIG# // your user name - email '623565791@qq.com' // #CONFIG# // your email - } - } - scm { - connection gitUrl - developerConnection gitUrl - url siteUrl - } - } - } - } -} - -task sourcesJar(type: Jar) { - from android.sourceSets.main.java.srcDirs - classifier = 'sources' -} - -task javadoc(type: Javadoc) { - source = android.sourceSets.main.java.srcDirs - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) +publish { + userOrg = 'hongyangandroid'//bintray.com用户名 + groupId = 'com.hyman'//jcenter上的路径 + artifactId = 'flowlayout-lib'//项目名称 + publishVersion = '1.1.2'//版本号 + desc = 'save time' + website = 'https://github.com/hongyangAndroid/FlowLayout' } - -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir -} - -artifacts { - archives javadocJar - archives sourcesJar -} - -Properties properties = new Properties() -properties.load(project.rootProject.file('local.properties').newDataInputStream()) -bintray { - user = properties.getProperty("bintray.user") - key = properties.getProperty("bintray.apikey") - configurations = ['archives'] - pkg { - repo = "maven" - name = "flowlayout" // #CONFIG# project name in jcenter - websiteUrl = siteUrl - vcsUrl = gitUrl - licenses = ["Apache-2.0"] - publish = true - } -} - diff --git a/flowlayout-lib/flowlayout-lib.iml b/flowlayout-lib/flowlayout-lib.iml index fb6d7d6..3f22574 100644 --- a/flowlayout-lib/flowlayout-lib.iml +++ b/flowlayout-lib/flowlayout-lib.iml @@ -1,5 +1,5 @@ - + @@ -9,13 +9,9 @@ - + - + + - + + - + - + + + + + + + + - + + + + + + + + - - - + + + - - - + + + + + + - - - + + - - - + - + + - - + - - - + + + + + + + \ No newline at end of file diff --git a/flowlayout-lib/src/main/AndroidManifest.xml b/flowlayout-lib/src/main/AndroidManifest.xml index 62f8380..e92bbe1 100644 --- a/flowlayout-lib/src/main/AndroidManifest.xml +++ b/flowlayout-lib/src/main/AndroidManifest.xml @@ -1,10 +1,6 @@ + > - - diff --git a/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/FlowLayout.java b/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/FlowLayout.java index f05f587..57850b5 100755 --- a/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/FlowLayout.java +++ b/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/FlowLayout.java @@ -3,42 +3,53 @@ import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; +import android.util.LayoutDirection; import android.view.View; import android.view.ViewGroup; +import android.support.v4.text.TextUtilsCompat; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Locale; -public class FlowLayout extends ViewGroup -{ +public class FlowLayout extends ViewGroup { private static final String TAG = "FlowLayout"; + private static final int LEFT = -1; + private static final int CENTER = 0; + private static final int RIGHT = 1; + protected List> mAllViews = new ArrayList>(); protected List mLineHeight = new ArrayList(); - private String mGravity; + protected List mLineWidth = new ArrayList(); + private int mGravity; + private List lineViews = new ArrayList<>(); - public FlowLayout(Context context, AttributeSet attrs, int defStyle) - { + public FlowLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TagFlowLayout); - mGravity = ta.getString(R.styleable.TagFlowLayout_gravity); - if (mGravity == null) - mGravity = getResources().getString(R.string.gravity_left); + mGravity = ta.getInt(R.styleable.TagFlowLayout_tag_gravity, LEFT); + int layoutDirection = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()); + if (layoutDirection == LayoutDirection.RTL) { + if (mGravity == LEFT) { + mGravity = RIGHT; + } else { + mGravity = LEFT; + } + } ta.recycle(); } - public FlowLayout(Context context, AttributeSet attrs) - { + public FlowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } - public FlowLayout(Context context) - { + public FlowLayout(Context context) { this(context, null); } @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) - { + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int modeWidth = MeasureSpec.getMode(widthMeasureSpec); int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); @@ -53,13 +64,10 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) int cCount = getChildCount(); - for (int i = 0; i < cCount; i++) - { + for (int i = 0; i < cCount; i++) { View child = getChildAt(i); - if (child.getVisibility() == View.GONE) - { - if (i == cCount - 1) - { + if (child.getVisibility() == View.GONE) { + if (i == cCount - 1) { width = Math.max(lineWidth, width); height += lineHeight; } @@ -74,19 +82,16 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; - if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) - { + if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) { width = Math.max(width, lineWidth); lineWidth = childWidth; height += lineHeight; lineHeight = childHeight; - } else - { + } else { lineWidth += childWidth; lineHeight = Math.max(lineHeight, childHeight); } - if (i == cCount - 1) - { + if (i == cCount - 1) { width = Math.max(lineWidth, width); height += lineHeight; } @@ -101,22 +106,20 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) - { + protected void onLayout(boolean changed, int l, int t, int r, int b) { mAllViews.clear(); mLineHeight.clear(); + mLineWidth.clear(); + lineViews.clear(); int width = getWidth(); int lineWidth = 0; int lineHeight = 0; - List lineViews = new ArrayList(); - int cCount = getChildCount(); - for (int i = 0; i < cCount; i++) - { + for (int i = 0; i < cCount; i++) { View child = getChildAt(i); if (child.getVisibility() == View.GONE) continue; MarginLayoutParams lp = (MarginLayoutParams) child @@ -125,10 +128,10 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); - if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width - getPaddingLeft() - getPaddingRight()) - { + if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width - getPaddingLeft() - getPaddingRight()) { mLineHeight.add(lineHeight); mAllViews.add(lineViews); + mLineWidth.add(lineWidth); lineWidth = 0; lineHeight = childHeight + lp.topMargin + lp.bottomMargin; @@ -141,6 +144,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) } mLineHeight.add(lineHeight); + mLineWidth.add(lineWidth); mAllViews.add(lineViews); @@ -149,17 +153,30 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) int lineNum = mAllViews.size(); - for (int i = 0; i < lineNum; i++) - { + for (int i = 0; i < lineNum; i++) { lineViews = mAllViews.get(i); lineHeight = mLineHeight.get(i); - left = getStartLeft(lineViews); - for (int j = 0; j < lineViews.size(); j++) - { + // set gravity + int currentLineWidth = this.mLineWidth.get(i); + switch (this.mGravity) { + case LEFT: + left = getPaddingLeft(); + break; + case CENTER: + left = (width - currentLineWidth) / 2 + getPaddingLeft(); + break; + case RIGHT: + // 适配了rtl,需要补偿一个padding值 + left = width - (currentLineWidth + getPaddingLeft()) - getPaddingRight(); + // 适配了rtl,需要把lineViews里面的数组倒序排 + Collections.reverse(lineViews); + break; + } + + for (int j = 0; j < lineViews.size(); j++) { View child = lineViews.get(j); - if (child.getVisibility() == View.GONE) - { + if (child.getVisibility() == View.GONE) { continue; } @@ -181,50 +198,18 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) } - private int getStartLeft(List lineViews) { - int left = getPaddingLeft(); - - int needWidth = 0; - for (int j = 0; j < lineViews.size(); j++) { - View child = lineViews.get(j); - if (child.getVisibility() == View.GONE) { - continue; - } - - MarginLayoutParams lp = (MarginLayoutParams) child - .getLayoutParams(); - needWidth += child.getMeasuredWidth() + lp.leftMargin - + lp.rightMargin; - } - - needWidth += getPaddingLeft() + getPaddingRight(); - if (mGravity.equals(getResources().getString(R.string.gravity_center))) { - if (getMeasuredWidth() > needWidth) { - left += (getMeasuredWidth() - needWidth) / 2; - } - } else if (mGravity.equals(getResources().getString(R.string.gravity_right))) { - if (getMeasuredWidth() > needWidth) { - left += getMeasuredWidth() - needWidth; - } - } - return left; - } - @Override - public LayoutParams generateLayoutParams(AttributeSet attrs) - { + public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } @Override - protected LayoutParams generateDefaultLayoutParams() - { + protected LayoutParams generateDefaultLayoutParams() { return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); } @Override - protected LayoutParams generateLayoutParams(LayoutParams p) - { + protected LayoutParams generateLayoutParams(LayoutParams p) { return new MarginLayoutParams(p); } } diff --git a/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/TagAdapter.java b/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/TagAdapter.java index 849fb1a..61b73a1 100644 --- a/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/TagAdapter.java +++ b/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/TagAdapter.java @@ -1,66 +1,89 @@ package com.zhy.view.flowlayout; +import android.util.Log; import android.view.View; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Set; -public abstract class TagAdapter -{ +public abstract class TagAdapter { private List mTagDatas; private OnDataChangedListener mOnDataChangedListener; + @Deprecated private HashSet mCheckedPosList = new HashSet(); - public TagAdapter(List datas) - { + public TagAdapter(List datas) { mTagDatas = datas; } - public TagAdapter(T[] datas) - { + @Deprecated + public TagAdapter(T[] datas) { mTagDatas = new ArrayList(Arrays.asList(datas)); } - static interface OnDataChangedListener - { + interface OnDataChangedListener { void onChanged(); } - void setOnDataChangedListener(OnDataChangedListener listener) - { + void setOnDataChangedListener(OnDataChangedListener listener) { mOnDataChangedListener = listener; } - public void setSelectedList(int... pos) - { - for (int i = 0; i < pos.length; i++) - mCheckedPosList.add(pos[i]); + @Deprecated + public void setSelectedList(int... poses) { + Set set = new HashSet<>(); + for (int pos : poses) { + set.add(pos); + } + setSelectedList(set); + } + + @Deprecated + public void setSelectedList(Set set) { + mCheckedPosList.clear(); + if (set != null) { + mCheckedPosList.addAll(set); + } notifyDataChanged(); } - HashSet getPreCheckedList() - { + @Deprecated + HashSet getPreCheckedList() { return mCheckedPosList; } - public int getCount() - { + public int getCount() { return mTagDatas == null ? 0 : mTagDatas.size(); } - public void notifyDataChanged() - { - mOnDataChangedListener.onChanged(); + public void notifyDataChanged() { + if (mOnDataChangedListener != null) + mOnDataChangedListener.onChanged(); } - public T getItem(int position) - { + public T getItem(int position) { return mTagDatas.get(position); } public abstract View getView(FlowLayout parent, int position, T t); -} \ No newline at end of file + + public void onSelected(int position, View view){ + Log.d("zhy","onSelected " + position); + } + + public void unSelected(int position, View view){ + Log.d("zhy","unSelected " + position); + } + + public boolean setSelected(int position, T t) { + return false; + } + + +} diff --git a/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/TagFlowLayout.java b/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/TagFlowLayout.java index b8b2bc8..ba90897 100644 --- a/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/TagFlowLayout.java +++ b/flowlayout-lib/src/main/java/com/zhy/view/flowlayout/TagFlowLayout.java @@ -10,6 +10,8 @@ import android.util.Log; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; import java.util.HashSet; import java.util.Iterator; @@ -18,230 +20,195 @@ /** * Created by zhy on 15/9/10. */ -public class TagFlowLayout extends FlowLayout implements TagAdapter.OnDataChangedListener -{ +public class TagFlowLayout extends FlowLayout + implements TagAdapter.OnDataChangedListener { + private TagAdapter mTagAdapter; - private boolean mAutoSelectEffect = true; private int mSelectedMax = -1;//-1为不限制数量 private static final String TAG = "TagFlowLayout"; - private MotionEvent mMotionEvent; private Set mSelectedView = new HashSet(); + private OnSelectListener mOnSelectListener; + private OnTagClickListener mOnTagClickListener; + + public interface OnSelectListener { + void onSelected(Set selectPosSet); + } - public TagFlowLayout(Context context, AttributeSet attrs, int defStyle) - { + public interface OnTagClickListener { + boolean onTagClick(View view, int position, FlowLayout parent); + } + + public TagFlowLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TagFlowLayout); - mAutoSelectEffect = ta.getBoolean(R.styleable.TagFlowLayout_auto_select_effect, true); mSelectedMax = ta.getInt(R.styleable.TagFlowLayout_max_select, -1); ta.recycle(); - - if (mAutoSelectEffect) - { - setClickable(true); - } } - public TagFlowLayout(Context context, AttributeSet attrs) - { + public TagFlowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } - public TagFlowLayout(Context context) - { + public TagFlowLayout(Context context) { this(context, null); } @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) - { + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int cCount = getChildCount(); - - for (int i = 0; i < cCount; i++) - { + for (int i = 0; i < cCount; i++) { TagView tagView = (TagView) getChildAt(i); - if (tagView.getVisibility() == View.GONE) continue; - if (tagView.getTagView().getVisibility() == View.GONE) - { + if (tagView.getVisibility() == View.GONE) { + continue; + } + if (tagView.getTagView().getVisibility() == View.GONE) { tagView.setVisibility(View.GONE); } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } - public interface OnSelectListener - { - void onSelected(Set selectPosSet); - } - private OnSelectListener mOnSelectListener; - - public void setOnSelectListener(OnSelectListener onSelectListener) - { + public void setOnSelectListener(OnSelectListener onSelectListener) { mOnSelectListener = onSelectListener; - if (mOnSelectListener != null) setClickable(true); } - public interface OnTagClickListener - { - boolean onTagClick(View view, int position, FlowLayout parent); - } - - private OnTagClickListener mOnTagClickListener; - - public void setOnTagClickListener(OnTagClickListener onTagClickListener) - { + public void setOnTagClickListener(OnTagClickListener onTagClickListener) { mOnTagClickListener = onTagClickListener; - if (onTagClickListener != null) setClickable(true); } - - public void setAdapter(TagAdapter adapter) - { - //if (mTagAdapter == adapter) - // return; + public void setAdapter(TagAdapter adapter) { mTagAdapter = adapter; mTagAdapter.setOnDataChangedListener(this); + mSelectedView.clear(); changeAdapter(); - } - private void changeAdapter() - { + @SuppressWarnings("ResourceType") + private void changeAdapter() { removeAllViews(); TagAdapter adapter = mTagAdapter; TagView tagViewContainer = null; HashSet preCheckedList = mTagAdapter.getPreCheckedList(); - for (int i = 0; i < adapter.getCount(); i++) - { + for (int i = 0; i < adapter.getCount(); i++) { View tagView = adapter.getView(this, i, adapter.getItem(i)); tagViewContainer = new TagView(getContext()); -// ViewGroup.MarginLayoutParams clp = (ViewGroup.MarginLayoutParams) tagView.getLayoutParams(); -// ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(clp); -// lp.width = ViewGroup.LayoutParams.WRAP_CONTENT; -// lp.height = ViewGroup.LayoutParams.WRAP_CONTENT; -// lp.topMargin = clp.topMargin; -// lp.bottomMargin = clp.bottomMargin; -// lp.leftMargin = clp.leftMargin; -// lp.rightMargin = clp.rightMargin; tagView.setDuplicateParentStateEnabled(true); - tagViewContainer.setLayoutParams(tagView.getLayoutParams()); + if (tagView.getLayoutParams() != null) { + tagViewContainer.setLayoutParams(tagView.getLayoutParams()); + + + } else { + MarginLayoutParams lp = new MarginLayoutParams( + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + lp.setMargins(dip2px(getContext(), 5), + dip2px(getContext(), 5), + dip2px(getContext(), 5), + dip2px(getContext(), 5)); + tagViewContainer.setLayoutParams(lp); + } + LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + tagView.setLayoutParams(lp); tagViewContainer.addView(tagView); addView(tagViewContainer); - - if(preCheckedList.contains(i)) - { - tagViewContainer.setChecked(true); + if (preCheckedList.contains(i)) { + setChildChecked(i, tagViewContainer); } - } - mSelectedView.addAll(preCheckedList); - } - - - @Override - public boolean onTouchEvent(MotionEvent event) - { - if (event.getAction() == MotionEvent.ACTION_UP) - { - mMotionEvent = MotionEvent.obtain(event); - } - return super.onTouchEvent(event); - } - - @Override - public boolean performClick() - { - if (mMotionEvent == null) return super.performClick(); - - int x = (int) mMotionEvent.getX(); - int y = (int) mMotionEvent.getY(); - mMotionEvent = null; - - TagView child = findChild(x, y); - int pos = findPosByView(child); - if (child != null) - { - doSelect(child, pos); - if (mOnTagClickListener != null) - { - return mOnTagClickListener.onTagClick(child.getTagView(), pos, this); + if (mTagAdapter.setSelected(i, adapter.getItem(i))) { + setChildChecked(i, tagViewContainer); } + tagView.setClickable(false); + final TagView finalTagViewContainer = tagViewContainer; + final int position = i; + tagViewContainer.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + doSelect(finalTagViewContainer, position); + if (mOnTagClickListener != null) { + mOnTagClickListener.onTagClick(finalTagViewContainer, position, + TagFlowLayout.this); + } + } + }); } - return super.performClick(); + mSelectedView.addAll(preCheckedList); } - - public void setMaxSelectCount(int count) - { - if (mSelectedView.size() > count) - { + public void setMaxSelectCount(int count) { + if (mSelectedView.size() > count) { Log.w(TAG, "you has already select more than " + count + " views , so it will be clear ."); mSelectedView.clear(); } mSelectedMax = count; } - public Set getSelectedList() - { + public Set getSelectedList() { return new HashSet(mSelectedView); } - private void doSelect(TagView child, int position) - { - if (mAutoSelectEffect) - { - if (!child.isChecked()) - { - //处理max_select=1的情况 - if(mSelectedMax == 1 && mSelectedView.size() == 1) - { - Iterator iterator = mSelectedView.iterator(); - Integer preIndex = iterator.next(); - TagView pre = (TagView) getChildAt(preIndex); - pre.setChecked(false); - child.setChecked(true); - mSelectedView.remove(preIndex); - mSelectedView.add(position); - }else - { - if (mSelectedMax > 0 && mSelectedView.size() >= mSelectedMax) - return; - child.setChecked(true); - mSelectedView.add(position); + private void setChildChecked(int position, TagView view) { + view.setChecked(true); + mTagAdapter.onSelected(position, view.getTagView()); + } + + private void setChildUnChecked(int position, TagView view) { + view.setChecked(false); + mTagAdapter.unSelected(position, view.getTagView()); + } + + private void doSelect(TagView child, int position) { + if (!child.isChecked()) { + //处理max_select=1的情况 + if (mSelectedMax == 1 && mSelectedView.size() == 1) { + Iterator iterator = mSelectedView.iterator(); + Integer preIndex = iterator.next(); + TagView pre = (TagView) getChildAt(preIndex); + setChildUnChecked(preIndex, pre); + setChildChecked(position, child); + + mSelectedView.remove(preIndex); + mSelectedView.add(position); + } else { + if (mSelectedMax > 0 && mSelectedView.size() >= mSelectedMax) { + return; } - } else - { - child.setChecked(false); - mSelectedView.remove(position); - } - if (mOnSelectListener != null) - { - mOnSelectListener.onSelected(new HashSet(mSelectedView)); + setChildChecked(position, child); + mSelectedView.add(position); } + } else { + setChildUnChecked(position, child); + mSelectedView.remove(position); + } + if (mOnSelectListener != null) { + mOnSelectListener.onSelected(new HashSet(mSelectedView)); } } + public TagAdapter getAdapter() { + return mTagAdapter; + } + + private static final String KEY_CHOOSE_POS = "key_choose_pos"; private static final String KEY_DEFAULT = "key_default"; @Override - protected Parcelable onSaveInstanceState() - { + protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable(KEY_DEFAULT, super.onSaveInstanceState()); String selectPos = ""; - if (mSelectedView.size() > 0) - { - for (int key : mSelectedView) - { + if (mSelectedView.size() > 0) { + for (int key : mSelectedView) { selectPos += key + "|"; } selectPos = selectPos.substring(0, selectPos.length() - 1); @@ -251,22 +218,20 @@ protected Parcelable onSaveInstanceState() } @Override - protected void onRestoreInstanceState(Parcelable state) - { - if (state instanceof Bundle) - { + protected void onRestoreInstanceState(Parcelable state) { + if (state instanceof Bundle) { Bundle bundle = (Bundle) state; String mSelectPos = bundle.getString(KEY_CHOOSE_POS); - if (!TextUtils.isEmpty(mSelectPos)) - { + if (!TextUtils.isEmpty(mSelectPos)) { String[] split = mSelectPos.split("\\|"); - for (String pos : split) - { + for (String pos : split) { int index = Integer.parseInt(pos); mSelectedView.add(index); TagView tagView = (TagView) getChildAt(index); - tagView.setChecked(true); + if (tagView != null) { + setChildChecked(index, tagView); + } } } @@ -276,39 +241,15 @@ protected void onRestoreInstanceState(Parcelable state) super.onRestoreInstanceState(state); } - private int findPosByView(View child) - { - final int cCount = getChildCount(); - for (int i = 0; i < cCount; i++) - { - View v = getChildAt(i); - if (v == child) return i; - } - return -1; - } - - private TagView findChild(int x, int y) - { - final int cCount = getChildCount(); - for (int i = 0; i < cCount; i++) - { - TagView v = (TagView) getChildAt(i); - if (v.getVisibility() == View.GONE) continue; - Rect outRect = new Rect(); - v.getHitRect(outRect); - if (outRect.contains(x, y)) - { - return v; - } - } - return null; - } @Override - public void onChanged() - { + public void onChanged() { + mSelectedView.clear(); changeAdapter(); } - + public static int dip2px(Context context, float dpValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } } diff --git a/flowlayout-lib/src/main/res/values/attrs.xml b/flowlayout-lib/src/main/res/values/attrs.xml index f341836..d1454ed 100644 --- a/flowlayout-lib/src/main/res/values/attrs.xml +++ b/flowlayout-lib/src/main/res/values/attrs.xml @@ -1,8 +1,11 @@ - - + + + + + \ No newline at end of file diff --git a/flowlayout/build.gradle b/flowlayout/build.gradle index 2a92bb7..97325f6 100644 --- a/flowlayout/build.gradle +++ b/flowlayout/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 22 - buildToolsVersion "23.0.0 rc3" + compileSdkVersion 25 + buildToolsVersion "25.0.3" defaultConfig { applicationId "com.zhy.flowlayout" minSdkVersion 10 - targetSdkVersion 22 + targetSdkVersion 25 versionCode 1 versionName "1.0" } @@ -21,7 +21,8 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:22.2.1' + compile 'com.android.support:appcompat-v7:25.3.0' compile project(':flowlayout-lib') - compile 'com.android.support:design:22.2.0' + compile 'com.android.support:design:25.3.0' + compile 'com.zhy:base-adapter:2.0.1' } diff --git a/flowlayout/flowlayout.iml b/flowlayout/flowlayout.iml index 7c907a3..33086c4 100644 --- a/flowlayout/flowlayout.iml +++ b/flowlayout/flowlayout.iml @@ -1,5 +1,5 @@ - + @@ -9,13 +9,9 @@ - + - + + - + + - + - + + + + + + + + - + + + + + + + + - + - + - - - - - - + + + + + + + + + + + + + - - - - + + - - + + - + - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/flowlayout/src/main/java/com/zhy/flowlayout/CategoryActivity.java b/flowlayout/src/main/java/com/zhy/flowlayout/CategoryActivity.java index 2ac28d3..fb6c41f 100644 --- a/flowlayout/src/main/java/com/zhy/flowlayout/CategoryActivity.java +++ b/flowlayout/src/main/java/com/zhy/flowlayout/CategoryActivity.java @@ -15,7 +15,7 @@ public class CategoryActivity extends AppCompatActivity private String[] mTabTitles = new String[] {"Muli Selected", "Limit 3", - "Event Test", "ScrollView Test","Single Choose"}; + "Event Test", "ScrollView Test", "Single Choose", "Gravity", "ListView Sample"}; @Override @@ -44,6 +44,10 @@ public Fragment getItem(int i) return new ScrollViewTestFragment(); case 4: return new SingleChooseFragment(); + case 5: + return new GravityFragment(); + case 6: + return new ListViewTestFragment(); default: return new EventTestFragment(); } diff --git a/flowlayout/src/main/java/com/zhy/flowlayout/EventTestFragment.java b/flowlayout/src/main/java/com/zhy/flowlayout/EventTestFragment.java index 6af2d1b..2bb6985 100644 --- a/flowlayout/src/main/java/com/zhy/flowlayout/EventTestFragment.java +++ b/flowlayout/src/main/java/com/zhy/flowlayout/EventTestFragment.java @@ -31,7 +31,7 @@ public class EventTestFragment extends Fragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.activity_main, container, false); + return inflater.inflate(R.layout.fragment_event_test, container, false); } @Override @@ -51,6 +51,12 @@ public View getView(FlowLayout parent, int position, String s) tv.setText(s); return tv; } + + @Override + public boolean setSelected(int position, String s) + { + return s.equals("Android"); + } }); mFlowLayout.setOnTagClickListener(new TagFlowLayout.OnTagClickListener() diff --git a/flowlayout/src/main/java/com/zhy/flowlayout/GravityFragment.java b/flowlayout/src/main/java/com/zhy/flowlayout/GravityFragment.java new file mode 100644 index 0000000..0a1bfaf --- /dev/null +++ b/flowlayout/src/main/java/com/zhy/flowlayout/GravityFragment.java @@ -0,0 +1,18 @@ +package com.zhy.flowlayout; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +public class GravityFragment extends Fragment +{ + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + return inflater.inflate(R.layout.fragment_gravity_flow_layout, null); + } +} diff --git a/flowlayout/src/main/java/com/zhy/flowlayout/LimitSelectedFragment.java b/flowlayout/src/main/java/com/zhy/flowlayout/LimitSelectedFragment.java index c024444..86636e1 100644 --- a/flowlayout/src/main/java/com/zhy/flowlayout/LimitSelectedFragment.java +++ b/flowlayout/src/main/java/com/zhy/flowlayout/LimitSelectedFragment.java @@ -29,7 +29,7 @@ public class LimitSelectedFragment extends Fragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.activity_main, container, false); + return inflater.inflate(R.layout.fragment_event_test, container, false); } @Override diff --git a/flowlayout/src/main/java/com/zhy/flowlayout/ListViewTestFragment.java b/flowlayout/src/main/java/com/zhy/flowlayout/ListViewTestFragment.java new file mode 100644 index 0000000..8066f82 --- /dev/null +++ b/flowlayout/src/main/java/com/zhy/flowlayout/ListViewTestFragment.java @@ -0,0 +1,97 @@ +package com.zhy.flowlayout; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; +import android.widget.TextView; + +import com.zhy.base.adapter.ViewHolder; +import com.zhy.base.adapter.abslistview.CommonAdapter; +import com.zhy.view.flowlayout.FlowLayout; +import com.zhy.view.flowlayout.TagAdapter; +import com.zhy.view.flowlayout.TagFlowLayout; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created by zhy on 15/9/10. + */ +public class ListViewTestFragment extends Fragment +{ + + private List> mDatas = new ArrayList>(); + private ListView mListView; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + return inflater.inflate(R.layout.fragment_listview, container, false); + } + + @Override + public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) + { + initDatas(); + + mListView = (ListView) view.findViewById(R.id.id_listview); + mListView.setAdapter(new CommonAdapter>(getActivity(), R.layout.item_for_listview, mDatas) + { + Map> selectedMap = new HashMap>(); + + + @Override + public void convert(final ViewHolder viewHolder, List strings) + { + TagFlowLayout tagFlowLayout = viewHolder.getView(R.id.id_tagflowlayout); + + TagAdapter tagAdapter = new TagAdapter(strings) + { + @Override + public View getView(FlowLayout parent, int position, String o) + { + //can use viewholder + TextView tv = (TextView) mInflater.inflate(R.layout.tv, + parent, false); + tv.setText(o); + return tv; + } + }; + tagFlowLayout.setAdapter(tagAdapter); + //重置状态 + tagAdapter.setSelectedList(selectedMap.get(viewHolder.getItemPosition())); + + tagFlowLayout.setOnSelectListener(new TagFlowLayout.OnSelectListener() + { + @Override + public void onSelected(Set selectPosSet) + { + selectedMap.put(viewHolder.getItemPosition(), selectPosSet); + } + }); + } + }); + + } + + private void initDatas() + { + for (int i = 'A'; i < 'z'; i++) + { + List itemData = new ArrayList(3); + for (int j = 0; j < 3; j++) + { + itemData.add((char) i + ""); + } + mDatas.add(itemData); + } + } +} diff --git a/flowlayout/src/main/java/com/zhy/flowlayout/ScrollViewTestFragment.java b/flowlayout/src/main/java/com/zhy/flowlayout/ScrollViewTestFragment.java index 2960f97..6f7de01 100644 --- a/flowlayout/src/main/java/com/zhy/flowlayout/ScrollViewTestFragment.java +++ b/flowlayout/src/main/java/com/zhy/flowlayout/ScrollViewTestFragment.java @@ -43,7 +43,7 @@ public class ScrollViewTestFragment extends Fragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.activity_main_sc, container, false); + return inflater.inflate(R.layout.fragment_sc, container, false); } @Override diff --git a/flowlayout/src/main/java/com/zhy/flowlayout/SimpleFragment.java b/flowlayout/src/main/java/com/zhy/flowlayout/SimpleFragment.java index 32650f5..ec2d723 100644 --- a/flowlayout/src/main/java/com/zhy/flowlayout/SimpleFragment.java +++ b/flowlayout/src/main/java/com/zhy/flowlayout/SimpleFragment.java @@ -7,6 +7,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import android.widget.Toast; import com.zhy.view.flowlayout.FlowLayout; import com.zhy.view.flowlayout.TagAdapter; @@ -15,8 +16,7 @@ /** * Created by zhy on 15/9/10. */ -public class SimpleFragment extends Fragment -{ +public class SimpleFragment extends Fragment { private String[] mVals = new String[] {"Hello", "Android", "Weclome Hi ", "Button", "TextView", "Hello", "Android", "Weclome", "Button ImageView", "TextView", "Helloworld", @@ -26,27 +26,30 @@ public class SimpleFragment extends Fragment @Nullable @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) - { - return inflater.inflate(R.layout.activity_main, container, false); + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_event_test, container, false); } @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) - { + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { final LayoutInflater mInflater = LayoutInflater.from(getActivity()); mFlowLayout = (TagFlowLayout) view.findViewById(R.id.id_flowlayout); + mFlowLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Toast.makeText(getActivity(), "FlowLayout Clicked", Toast.LENGTH_SHORT).show(); + } + }); - mFlowLayout.setAdapter(new TagAdapter(mVals) - { + mFlowLayout.setAdapter(new TagAdapter(mVals) { @Override - public View getView(FlowLayout parent, int position, String s) - { + public View getView(FlowLayout parent, int position, String s) { TextView tv = (TextView) mInflater.inflate(R.layout.tv, mFlowLayout, false); tv.setText(s); return tv; } + }); } } diff --git a/flowlayout/src/main/res/layout/activity_category.xml b/flowlayout/src/main/res/layout/activity_category.xml index af0debb..cc13802 100644 --- a/flowlayout/src/main/res/layout/activity_category.xml +++ b/flowlayout/src/main/res/layout/activity_category.xml @@ -13,7 +13,7 @@ app:tabGravity="fill" android:background="#ffffff" app:tabIndicatorColor="#0ddcff" - app:tabMode="fixed" + app:tabMode="scrollable" app:tabSelectedTextColor="#0ddcff" app:tabTextColor="#000000"/> diff --git a/flowlayout/src/main/res/layout/activity_main.xml b/flowlayout/src/main/res/layout/activity_main.xml index c5d99bc..63dde54 100644 --- a/flowlayout/src/main/res/layout/activity_main.xml +++ b/flowlayout/src/main/res/layout/activity_main.xml @@ -10,7 +10,6 @@ android:layout_height="wrap_content" android:padding="20dp" zhy:max_select="-1" - zhy:gravity="@string/gravity_center" > diff --git a/flowlayout/src/main/res/layout/activity_main_sc.xml b/flowlayout/src/main/res/layout/activity_main_sc.xml index 8886f4e..b5c16ce 100644 --- a/flowlayout/src/main/res/layout/activity_main_sc.xml +++ b/flowlayout/src/main/res/layout/activity_main_sc.xml @@ -10,7 +10,6 @@ android:layout_height="wrap_content" android:padding="20dp" zhy:max_select="-1" - zhy:gravity="@string/gravity_center" > diff --git a/flowlayout/src/main/res/layout/fragment_event_test.xml b/flowlayout/src/main/res/layout/fragment_event_test.xml new file mode 100644 index 0000000..63dde54 --- /dev/null +++ b/flowlayout/src/main/res/layout/fragment_event_test.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/flowlayout/src/main/res/layout/fragment_gravity_flow_layout.xml b/flowlayout/src/main/res/layout/fragment_gravity_flow_layout.xml new file mode 100644 index 0000000..0a5aa69 --- /dev/null +++ b/flowlayout/src/main/res/layout/fragment_gravity_flow_layout.xml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/flowlayout/src/main/res/layout/fragment_listview.xml b/flowlayout/src/main/res/layout/fragment_listview.xml new file mode 100644 index 0000000..8398628 --- /dev/null +++ b/flowlayout/src/main/res/layout/fragment_listview.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/flowlayout/src/main/res/layout/fragment_sc.xml b/flowlayout/src/main/res/layout/fragment_sc.xml new file mode 100644 index 0000000..b5c16ce --- /dev/null +++ b/flowlayout/src/main/res/layout/fragment_sc.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/flowlayout/src/main/res/layout/fragment_single_choose.xml b/flowlayout/src/main/res/layout/fragment_single_choose.xml index ab6bee8..7592c3e 100644 --- a/flowlayout/src/main/res/layout/fragment_single_choose.xml +++ b/flowlayout/src/main/res/layout/fragment_single_choose.xml @@ -9,7 +9,6 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="20dp" - zhy:gravity="@string/gravity_center" zhy:max_select="1" > diff --git a/flowlayout/src/main/res/layout/item_for_listview.xml b/flowlayout/src/main/res/layout/item_for_listview.xml new file mode 100644 index 0000000..44af644 --- /dev/null +++ b/flowlayout/src/main/res/layout/item_for_listview.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ff2ac0e..b6cbdd5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Sep 30 14:01:04 GMT+08:00 2015 +#Tue Sep 12 16:51:04 CST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip