diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bdb0cab --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.travis.yml b/.travis.yml index 3c8a6ed..0804fe7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,37 +1,29 @@ -language: java +language: android jdk: oraclejdk7 branches: only: - master env: - matrix: - - ANDROID_TARGET=android-21 ANDROID_ABI=armeabi-v7a + global: + - ADB_INSTALL_TIMEOUT=8 # minutes (2 minutes by default) +android: + components: + - tools + - build-tools-23.0.2 + - android-23 -before_install: - # Install base Android SDK - - sudo apt-get update -qq - - if [ `uname -m` = x86_64 ]; then sudo apt-get install -qq --force-yes libgd2-xpm ia32-libs ia32-libs-multiarch > /dev/null; fi - - wget http://dl.google.com/android/android-sdk_r24.0.2-linux.tgz - - tar xzf android-sdk_r24.0.2-linux.tgz - - export ANDROID_HOME=$PWD/android-sdk-linux - - export PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools - - chmod +x gradlew + - extra-android-m2repository + + - sys-img-armeabi-v7a-android-23 - # Gradle - - wget http://services.gradle.org/distributions/gradle-1.12-bin.zip - - unzip gradle-1.12-bin.zip - - export GRADLE_HOME=$PWD/gradle-1.12 - - export PATH=$GRADLE_HOME/bin:$PATH + licenses: + - 'android-sdk-license-.+' - # Install required components - # For a full list, run `android list sdk -a --extended` - # Note that sysimg-19 downloads only ARM, because only the first license query is accepted. - - echo yes | android update sdk --filter platform-tools --no-ui --force > /dev/null - - echo yes | android update sdk --all --filter build-tools-21.1.1 --no-ui --force > /dev/null - - echo yes | android update sdk --filter android-21 --no-ui --force > /dev/null - - echo yes | android update sdk --filter sys-img-x86-android-19 --no-ui --force > /dev/null - - echo yes | android update sdk --filter extra-android-support --no-ui --force > /dev/null - - echo yes | android update sdk --filter extra-android-m2repository --no-ui --force > /dev/null +before_install: + - chmod +x gradlew -install: - - ./gradlew assemble \ No newline at end of file +before_script: + - echo no | android create avd --force -n test -t android-23 --abi armeabi-v7a + - emulator -avd test -no-skin -no-audio -no-window & + - android-wait-for-emulator + - adb shell input keyevent 82 & \ No newline at end of file diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index 5e48513..0000000 --- a/CHANGELOG +++ /dev/null @@ -1,35 +0,0 @@ -Change Log -========== - -Version 1.4 *(2015-05-23)* ----------------------------- - -- Fix: Duplicate "attr" name issues when using multiple Android libraries. - -Version 1.3 *(2015-05-21)* ----------------------------- - -- Attributes refactor. -- Add listener for detect tag click event. -- Fix: Interrupted click event by touch event. - - -Version 1.2 *(2015-04-14)* ----------------------------- - -- Fix: Google soft keyboard backspace issue. -- Add tag background color feature. - - -Version 1.1 *(2015-02-28)* ----------------------------- - -- Fix: EditorActionListener. -- Fix: Uncheck tag when user is typing. -- Add `submitTag()` to submit a new tag. - - -Version 1.0 *(2015-02-10)* ----------------------------- - -- Initial release. \ No newline at end of file diff --git a/README.md b/README.md index 2a6aa9f..825fac4 100644 --- a/README.md +++ b/README.md @@ -1,132 +1,72 @@ -# `AndroidTagGroup` +# AndroidTagGroup -[![Release 1.4](https://img.shields.io/badge/Release-1.4.1-green.svg)](https://github.com/2dxgujun/AndroidTagGroup/releases) -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/me.gujun.android.taggroup/library/badge.svg?style=flat)](https://maven-badges.herokuapp.com/maven-central/me.gujun.android.taggroup/library) -[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-AndroidTagGroup-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1539) -[![Build Status](https://travis-ci.org/2dxgujun/AndroidTagGroup.png?branch=master)](https://travis-ci.org/2dxgujun/AndroidTagGroup) - -The TagGroup is a special layout with a set of tags. You can use it to tag people, books or anything you want. - -Also you can contribute new idea to me. - -# Demo +AndroidTagGroup is a special layout with a set of tags. You can use it to tag people, books or anything you want. ### Screenshot ![screenshot1](http://ww4.sinaimg.cn/large/bce2dea9jw1esbsby9v5fj20u00w8jxx.jpg) - -### Edit Tags ![screenshot2](http://ww4.sinaimg.cn/large/bce2dea9jw1esbsbngv8fj20u005w75v.jpg) ![screenshot3](http://ww4.sinaimg.cn/large/bce2dea9jw1esbsbmoagij20u005sabl.jpg) -[Download Demo](https://github.com/2dxgujun/AndroidTagGroup/releases/download/v1.4/AndroidTagGroup-Demo-v1.4.apk) - -# Usage - -## Step 1 - -#### Gradle -```groovy -dependencies { - compile 'me.gujun.android.taggroup:library:1.4@aar' -} -``` - -#### Maven -```xml - - me.gujun.android.taggroup - library - 1.4 - apklib - -``` - -## Step 2 +## Usage +### Step 1 +Follow [these steps](https://jitpack.io/#alirezaaa/AndroidTagGroup/v1.7.3). +### Step 2 Use it in your own code: ```xml - + ``` ```java -TagGroup mTagGroup = (TagGroup) findViewById(R.id.tag_group); -mTagGroup.setTags(new String[]{"Tag1", "Tag2", "Tag3"}); +AndroidTagGroup mTagGroup = (AndroidTagGroup) findViewById(R.id.androidTagGroup); +mTagGroup.setTags(new String[]{"Tag 1", "Tag 2", "Tag 3"}); ``` -Use `setTags(...)` to set the initial tags in the group. - -#### How to submit a new tag? - -To "submit" a new tag as user press "Enter" or tap the blank area of the tag group, also you can "submit" a new tag via `submitTag()`. - -**Note**: Google keyboard (a few soft keyboard not honour the key event) currently not supported "Enter" key to "submit" a new tag. - -#### How to delete a tag? -To delete a tag as user press "Backspace" key or double-tap the tag which you want to delete. - -#### How to detect tag click event? - -Implement a callback interface: `TagGroup.OnTagClickListener`, and set the listener via `setOnTagClickListener()`. - - -# Build - -run `./gradlew assembleDebug` (Mac/Linux) - -or - -run `gradlew.bat assembleDebug` (Windows) +### Notes +- Use `setTags(...)` to set the initial tags in the group. +- To submit a new tag as user press "Enter" key or tap the blank area of the tag group, use `submitTag()`. +- To delete a tag as user press "Backspace", double-tap the tag which you want to delete. +- There are following interfaces to implement; `OnTagLimitationExceedListener`, `OnTagChangeListener`, and `OnTagClickListener`. # Attributes - -There are several attributes you can set: - -![Dimension illustrate](http://ww2.sinaimg.cn/large/bce2dea9gw1epov0i8x6kj20rk054q4g.jpg) - -| attr | default | mean | -|:------------------------- |:---------------- |:------------------------------------------------------- | -| atg_isAppendMode | false | Determine the TagGroup mode, APPEND or single DISPLAY. | -| atg_inputHint | Add Tag/添加标签 | The hint of the INPUT tag. | -| atg_borderColor | #49C120 | The tag outline border color. | -| atg_textColor | #49C120 | The tag text color. | -| atg_backgroundColor | #FFFFFF | The tag background color. | -| atg_dashBorderColor | #AAAAAA | The tag dash outline border color. | -| atg_inputHintColor | #80000000 | The input tag hint text color. | -| atg_inputTextColor | #DE000000 | The input tag type text color.. | -| atg_checkedBorderColor | #49C120 | The checked tag outline border color. | -| atg_checkedTextColor | #FFFFFF | The checked text color. | -| atg_checkedMarkerColor | #FFFFFF | The checked marker color. | -| atg_checkedBackgroundColor| #49C120 | The checked tag background color. | -| atg_pressedBackgroundColor| #EDEDED | The tag background color when the tag is being pressed. | -| atg_borderStrokeWidth | 0.5dp | The tag outline border stroke width. | -| atg_textSize | 13sp | The tag text size. | -| atg_horizontalSpacing | 8dp | The horizontal tag spacing.(Mark1) | -| atg_verticalSpacing | 4dp | The vertical tag spacing.(Mark2) | -| atg_horizontalPadding | 12dp | The horizontal tag padding.(Mark3) | -| atg_verticalPadding | 3dp | The vertical tag padding.(Mark4) | - -# Developed By - -Jun Gu - <2dxgujun@gmail.com> - - - Follow me on Weibo - - - Follow me on Google Plus - - -# License - +| Attribute | Default Value | Description | +|:------------------------------|:-----------------------|:--------------------------------------------------------| +| atg_isAppendMode | false | Determine the mode. | +| atg_inputHint | Add Tag | The hint of the INPUT tag. | +| atg_borderColor | #49C120 | The tag outline border color. | +| atg_textColor | #49C120 | The tag text color. | +| atg_backgroundColor | #FFFFFF | The tag background color. | +| atg_dashBorderColor | #AAAAAA | The tag dash outline border color. | +| atg_inputHintColor | #80000000 | The input tag hint text color. | +| atg_inputTextColor | #DE000000 | The input tag type text color.. | +| atg_checkedBorderColor | #49C120 | The checked tag outline border color. | +| atg_checkedTextColor | #FFFFFF | The checked text color. | +| atg_checkedMarkerColor | #FFFFFF | The checked marker color. | +| atg_checkedBackgroundColor | #49C120 | The checked tag background color. | +| atg_pressedBackgroundColor | #EDEDED | The tag background color when the tag is being pressed. | +| atg_borderStrokeWidth | 0.5dp | The tag outline border stroke width. | +| atg_textSize | 13sp | The tag text size. | +| atg_horizontalSpacing | 8dp | The horizontal tag spacing. | +| atg_verticalSpacing | 4dp | The vertical tag spacing. | +| atg_horizontalPadding | 12dp | The horizontal tag padding. | +| atg_verticalPadding | 3dp | The vertical tag padding. | +| atg_tagsLimitation | no limitation | Adding tags limitation | +| atg_charsLimitation | no limitation | Characters limitation | + +## Developed By +- Jun Gu - <2dxgujun@gmail.com> +- Alireza Eskandarpour Shoferi - + +## License Copyright 2015 Jun Gu Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/demo/.gitignore b/app/.gitignore similarity index 100% rename from demo/.gitignore rename to app/.gitignore diff --git a/demo/build.gradle b/app/build.gradle similarity index 63% rename from demo/build.gradle rename to app/build.gradle index 8b3ed8d..8f3aaa1 100644 --- a/demo/build.gradle +++ b/app/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 21 - buildToolsVersion '21.1.1' + compileSdkVersion 23 + buildToolsVersion '23.0.2' defaultConfig { - applicationId 'me.gujun.android.taggroup.demo' + applicationId 'me.gujun.android.taggroup.app' minSdkVersion 8 - targetSdkVersion 21 + targetSdkVersion 23 versionName project.VERSION_NAME versionCode Integer.parseInt(project.VERSION_CODE) } @@ -18,9 +18,13 @@ android { } productFlavors { } + // Travis CI needing + lintOptions { + abortOnError false + } } dependencies { compile project(':library') - compile 'com.android.support:appcompat-v7:21.0.3' + compile 'com.android.support:appcompat-v7:23.2.1' } \ No newline at end of file diff --git a/demo/proguard-rules.pro b/app/proguard-rules.pro similarity index 100% rename from demo/proguard-rules.pro rename to app/proguard-rules.pro diff --git a/demo/src/androidTest/java/me/gujun/android/taggroup/ApplicationTest.java b/app/src/androidTest/java/me/gujun/android/taggroup/ApplicationTest.java similarity index 100% rename from demo/src/androidTest/java/me/gujun/android/taggroup/ApplicationTest.java rename to app/src/androidTest/java/me/gujun/android/taggroup/ApplicationTest.java diff --git a/demo/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml similarity index 54% rename from demo/src/main/AndroidManifest.xml rename to app/src/main/AndroidManifest.xml index 732aefd..ae1c65d 100644 --- a/demo/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,26 +1,26 @@ - + - + android:theme="@style/AppTheme"> + - + - + + android:parentActivityName="me.gujun.android.taggroup.app.MainActivity"> + android:value="me.gujun.android.taggroup.app.MainActivity"/> diff --git a/demo/src/main/java/me/gujun/android/taggroup/demo/MainActivity.java b/app/src/main/java/me/gujun/android/taggroup/app/MainActivity.java similarity index 51% rename from demo/src/main/java/me/gujun/android/taggroup/demo/MainActivity.java rename to app/src/main/java/me/gujun/android/taggroup/app/MainActivity.java index 872bf9f..5c9e8e1 100644 --- a/demo/src/main/java/me/gujun/android/taggroup/demo/MainActivity.java +++ b/app/src/main/java/me/gujun/android/taggroup/app/MainActivity.java @@ -1,4 +1,4 @@ -package me.gujun.android.taggroup.demo; +package me.gujun.android.taggroup.app; import android.content.Intent; import android.os.Bundle; @@ -9,22 +9,22 @@ import android.widget.TextView; import android.widget.Toast; -import me.gujun.android.taggroup.TagGroup; -import me.gujun.android.taggroup.demo.db.TagsManager; +import me.gujun.android.taggroup.AndroidTagGroup; +import me.gujun.android.taggroup.app.db.TagsManager; public class MainActivity extends ActionBarActivity { private TextView mPromptText; - private TagGroup mDefaultTagGroup; - private TagGroup mSmallTagGroup; - private TagGroup mLargeTagGroup; - private TagGroup mBeautyTagGroup; - private TagGroup mBeautyInverseTagGroup; + private AndroidTagGroup mDefaultAndroidTagGroup; + private AndroidTagGroup mSmallAndroidTagGroup; + private AndroidTagGroup mLargeAndroidTagGroup; + private AndroidTagGroup mBeautyAndroidTagGroup; + private AndroidTagGroup mBeautyInverseAndroidTagGroup; private TagsManager mTagsManager; - private TagGroup.OnTagClickListener mTagClickListener = new TagGroup.OnTagClickListener() { + private AndroidTagGroup.OnTagClickListener mTagClickListener = new AndroidTagGroup.OnTagClickListener() { @Override public void onTagClick(String tag) { Toast.makeText(MainActivity.this, tag, Toast.LENGTH_SHORT).show(); @@ -47,32 +47,37 @@ public void onClick(View v) { } }); - mDefaultTagGroup = (TagGroup) findViewById(R.id.tag_group); - mSmallTagGroup = (TagGroup) findViewById(R.id.tag_group_small); - mLargeTagGroup = (TagGroup) findViewById(R.id.tag_group_large); - mBeautyTagGroup = (TagGroup) findViewById(R.id.tag_group_beauty); - mBeautyInverseTagGroup = (TagGroup) findViewById(R.id.tag_group_beauty_inverse); + mDefaultAndroidTagGroup = (AndroidTagGroup) findViewById(R.id.androidTagGroup); + mSmallAndroidTagGroup = (AndroidTagGroup) findViewById(R.id.tag_group_small); + mLargeAndroidTagGroup = (AndroidTagGroup) findViewById(R.id.tag_group_large); + mBeautyAndroidTagGroup = (AndroidTagGroup) findViewById(R.id.tag_group_beauty); + mBeautyInverseAndroidTagGroup = (AndroidTagGroup) findViewById(R.id.tag_group_beauty_inverse); if (tags != null && tags.length > 0) { - mDefaultTagGroup.setTags(tags); - mSmallTagGroup.setTags(tags); - mLargeTagGroup.setTags(tags); - mBeautyTagGroup.setTags(tags); - mBeautyInverseTagGroup.setTags(tags); + mDefaultAndroidTagGroup.setTags(tags); + mSmallAndroidTagGroup.setTags(tags); + mLargeAndroidTagGroup.setTags(tags); + mBeautyAndroidTagGroup.setTags(tags); + mBeautyInverseAndroidTagGroup.setTags(tags); } MyTagGroupOnClickListener tgClickListener = new MyTagGroupOnClickListener(); - mDefaultTagGroup.setOnClickListener(tgClickListener); - mSmallTagGroup.setOnClickListener(tgClickListener); - mLargeTagGroup.setOnClickListener(tgClickListener); - mBeautyTagGroup.setOnClickListener(tgClickListener); - mBeautyInverseTagGroup.setOnClickListener(tgClickListener); - - mDefaultTagGroup.setOnTagClickListener(mTagClickListener); - mSmallTagGroup.setOnTagClickListener(mTagClickListener); - mLargeTagGroup.setOnTagClickListener(mTagClickListener); - mBeautyTagGroup.setOnTagClickListener(mTagClickListener); - mBeautyInverseTagGroup.setOnTagClickListener(mTagClickListener); + mDefaultAndroidTagGroup.setOnClickListener(tgClickListener); + mSmallAndroidTagGroup.setOnClickListener(tgClickListener); + mLargeAndroidTagGroup.setOnClickListener(tgClickListener); + mBeautyAndroidTagGroup.setOnClickListener(tgClickListener); + mBeautyInverseAndroidTagGroup.setOnClickListener(tgClickListener); + + mDefaultAndroidTagGroup.setOnTagClickListener(mTagClickListener); + mSmallAndroidTagGroup.setOnTagClickListener(mTagClickListener); + mLargeAndroidTagGroup.setOnTagClickListener(mTagClickListener); + mBeautyAndroidTagGroup.setOnTagClickListener(mTagClickListener); + mBeautyInverseAndroidTagGroup.setOnTagClickListener(mTagClickListener); + } + + protected void launchTagEditorActivity() { + Intent intent = new Intent(MainActivity.this, TagEditorActivity.class); + startActivity(intent); } @Override @@ -80,11 +85,11 @@ protected void onResume() { super.onResume(); String[] tags = mTagsManager.getTags(); mPromptText.setVisibility((tags == null || tags.length == 0) ? View.VISIBLE : View.GONE); - mDefaultTagGroup.setTags(tags); - mSmallTagGroup.setTags(tags); - mLargeTagGroup.setTags(tags); - mBeautyTagGroup.setTags(tags); - mBeautyInverseTagGroup.setTags(tags); + mDefaultAndroidTagGroup.setTags(tags); + mSmallAndroidTagGroup.setTags(tags); + mLargeAndroidTagGroup.setTags(tags); + mBeautyAndroidTagGroup.setTags(tags); + mBeautyInverseAndroidTagGroup.setTags(tags); } @Override @@ -102,11 +107,6 @@ public boolean onOptionsItemSelected(MenuItem item) { return false; } - protected void launchTagEditorActivity() { - Intent intent = new Intent(MainActivity.this, TagEditorActivity.class); - startActivity(intent); - } - class MyTagGroupOnClickListener implements View.OnClickListener { @Override public void onClick(View v) { diff --git a/demo/src/main/java/me/gujun/android/taggroup/demo/TagEditorActivity.java b/app/src/main/java/me/gujun/android/taggroup/app/TagEditorActivity.java similarity index 69% rename from demo/src/main/java/me/gujun/android/taggroup/demo/TagEditorActivity.java rename to app/src/main/java/me/gujun/android/taggroup/app/TagEditorActivity.java index 27d2ea1..e1fb089 100644 --- a/demo/src/main/java/me/gujun/android/taggroup/demo/TagEditorActivity.java +++ b/app/src/main/java/me/gujun/android/taggroup/app/TagEditorActivity.java @@ -1,16 +1,16 @@ -package me.gujun.android.taggroup.demo; +package me.gujun.android.taggroup.app; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; -import me.gujun.android.taggroup.TagGroup; -import me.gujun.android.taggroup.demo.db.TagsManager; +import me.gujun.android.taggroup.AndroidTagGroup; +import me.gujun.android.taggroup.app.db.TagsManager; public class TagEditorActivity extends ActionBarActivity { - private TagGroup mTagGroup; + private AndroidTagGroup mAndroidTagGroup; private TagsManager mTagsManager; @Override @@ -21,8 +21,8 @@ protected void onCreate(Bundle savedInstanceState) { mTagsManager = TagsManager.getInstance(getApplicationContext()); String[] tags = mTagsManager.getTags(); - mTagGroup = (TagGroup) findViewById(R.id.tag_group); - mTagGroup.setTags(tags); + mAndroidTagGroup = (AndroidTagGroup) findViewById(R.id.androidTagGroup); + mAndroidTagGroup.setTags(tags); } @Override @@ -34,11 +34,11 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { - mTagsManager.updateTags(mTagGroup.getTags()); + mTagsManager.updateTags(mAndroidTagGroup.getTags()); finish(); return true; } else if (item.getItemId() == R.id.action_submit) { - mTagGroup.submitTag(); + mAndroidTagGroup.submitTag(); return true; } return false; @@ -46,7 +46,7 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onBackPressed() { - mTagsManager.updateTags(mTagGroup.getTags()); + mTagsManager.updateTags(mAndroidTagGroup.getTags()); super.onBackPressed(); } } \ No newline at end of file diff --git a/demo/src/main/java/me/gujun/android/taggroup/demo/db/DatabaseHelper.java b/app/src/main/java/me/gujun/android/taggroup/app/db/DatabaseHelper.java similarity index 94% rename from demo/src/main/java/me/gujun/android/taggroup/demo/db/DatabaseHelper.java rename to app/src/main/java/me/gujun/android/taggroup/app/db/DatabaseHelper.java index ba10f8d..d72b4b7 100644 --- a/demo/src/main/java/me/gujun/android/taggroup/demo/db/DatabaseHelper.java +++ b/app/src/main/java/me/gujun/android/taggroup/app/db/DatabaseHelper.java @@ -1,4 +1,4 @@ -package me.gujun.android.taggroup.demo.db; +package me.gujun.android.taggroup.app.db; import android.content.Context; import android.database.sqlite.SQLiteDatabase; diff --git a/demo/src/main/java/me/gujun/android/taggroup/demo/db/TagsManager.java b/app/src/main/java/me/gujun/android/taggroup/app/db/TagsManager.java similarity index 97% rename from demo/src/main/java/me/gujun/android/taggroup/demo/db/TagsManager.java rename to app/src/main/java/me/gujun/android/taggroup/app/db/TagsManager.java index 841fc28..aabc1de 100644 --- a/demo/src/main/java/me/gujun/android/taggroup/demo/db/TagsManager.java +++ b/app/src/main/java/me/gujun/android/taggroup/app/db/TagsManager.java @@ -1,4 +1,4 @@ -package me.gujun.android.taggroup.demo.db; +package me.gujun.android.taggroup.app.db; import android.content.ContentValues; import android.content.Context; @@ -52,17 +52,17 @@ public void updateTags(CharSequence... tags) { } } - public void addTag(CharSequence tag) { - ContentValues values = new ContentValues(); + public void clearTags() { SQLiteDatabase db = mDbHelper.getWritableDatabase(); - values.put(TagsTable.TAG, tag.toString()); - db.insert(TagsTable.TABLE_NAME, null, values); + db.delete(TagsTable.TABLE_NAME, null, null); db.close(); } - public void clearTags() { + public void addTag(CharSequence tag) { + ContentValues values = new ContentValues(); SQLiteDatabase db = mDbHelper.getWritableDatabase(); - db.delete(TagsTable.TABLE_NAME, null, null); + values.put(TagsTable.TAG, tag.toString()); + db.insert(TagsTable.TABLE_NAME, null, values); db.close(); } } \ No newline at end of file diff --git a/demo/src/main/java/me/gujun/android/taggroup/demo/db/TagsTable.java b/app/src/main/java/me/gujun/android/taggroup/app/db/TagsTable.java similarity index 87% rename from demo/src/main/java/me/gujun/android/taggroup/demo/db/TagsTable.java rename to app/src/main/java/me/gujun/android/taggroup/app/db/TagsTable.java index b05a5c1..e2864cb 100644 --- a/demo/src/main/java/me/gujun/android/taggroup/demo/db/TagsTable.java +++ b/app/src/main/java/me/gujun/android/taggroup/app/db/TagsTable.java @@ -1,4 +1,4 @@ -package me.gujun.android.taggroup.demo.db; +package me.gujun.android.taggroup.app.db; import android.provider.BaseColumns; diff --git a/demo/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml similarity index 56% rename from demo/src/main/res/layout/activity_main.xml rename to app/src/main/res/layout/activity_main.xml index db8f830..b33684c 100644 --- a/demo/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,19 +1,19 @@ + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:paddingBottom="@dimen/activity_vertical_margin" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + tools:context=".MainActivity"> + android:textSize="16sp"/> + android:textColor="@android:color/darker_gray"/> - + + android:background="#DDD"/> - + android:layout_marginTop="5dp"/> + android:background="#DDD"/> - + android:layout_marginTop="5dp"/> + android:textSize="14sp"/> - + android:layout_marginTop="10dp"/> + android:textSize="18sp"/> - + android:layout_marginTop="10dp"/> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_tag_editor.xml b/app/src/main/res/layout/activity_tag_editor.xml new file mode 100644 index 0000000..1f2da8f --- /dev/null +++ b/app/src/main/res/layout/activity_tag_editor.xml @@ -0,0 +1,15 @@ + + + + \ No newline at end of file diff --git a/demo/src/main/res/menu/menu_main_activity.xml b/app/src/main/res/menu/menu_main_activity.xml similarity index 67% rename from demo/src/main/res/menu/menu_main_activity.xml rename to app/src/main/res/menu/menu_main_activity.xml index f1764e9..1b8bd5f 100644 --- a/demo/src/main/res/menu/menu_main_activity.xml +++ b/app/src/main/res/menu/menu_main_activity.xml @@ -1,8 +1,8 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> + app:showAsAction="always"/> \ No newline at end of file diff --git a/demo/src/main/res/menu/menu_tag_editor_activity.xml b/app/src/main/res/menu/menu_tag_editor_activity.xml similarity index 67% rename from demo/src/main/res/menu/menu_tag_editor_activity.xml rename to app/src/main/res/menu/menu_tag_editor_activity.xml index 6d473cf..567904b 100644 --- a/demo/src/main/res/menu/menu_tag_editor_activity.xml +++ b/app/src/main/res/menu/menu_tag_editor_activity.xml @@ -1,8 +1,8 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> + app:showAsAction="always"/> \ No newline at end of file diff --git a/demo/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from demo/src/main/res/mipmap-hdpi/ic_launcher.png rename to app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/demo/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from demo/src/main/res/mipmap-mdpi/ic_launcher.png rename to app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/demo/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from demo/src/main/res/mipmap-xhdpi/ic_launcher.png rename to app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from demo/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/demo/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml similarity index 100% rename from demo/src/main/res/values-w820dp/dimens.xml rename to app/src/main/res/values-w820dp/dimens.xml diff --git a/demo/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml similarity index 100% rename from demo/src/main/res/values/dimens.xml rename to app/src/main/res/values/dimens.xml diff --git a/demo/src/main/res/values-en/strings.xml b/app/src/main/res/values/strings.xml similarity index 70% rename from demo/src/main/res/values-en/strings.xml rename to app/src/main/res/values/strings.xml index 5f2428d..e012f49 100644 --- a/demo/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,9 +1,11 @@ - TagGroup-Demo + AndroidTagGroup Demo Add Tags Edit Tags Tags (Default) Tags (Large) Tags (Small) + Edit + Submit \ No newline at end of file diff --git a/demo/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml similarity index 100% rename from demo/src/main/res/values/styles.xml rename to app/src/main/res/values/styles.xml diff --git a/build.gradle b/build.gradle index cd74ded..e9e7e83 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.2.3' + classpath 'com.android.tools.build:gradle:1.5.0' } } diff --git a/demo/src/main/res/layout/activity_tag_editor.xml b/demo/src/main/res/layout/activity_tag_editor.xml deleted file mode 100644 index 6749944..0000000 --- a/demo/src/main/res/layout/activity_tag_editor.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - \ No newline at end of file diff --git a/demo/src/main/res/values/strings.xml b/demo/src/main/res/values/strings.xml deleted file mode 100644 index 88f07de..0000000 --- a/demo/src/main/res/values/strings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - TagGroup-Demo - 编辑标签 - 添加标签 - 标签(默认) - 标签(小号) - 标签(大号) - Submit - Edit - diff --git a/gradle.properties b/gradle.properties index e61bff9..c0552be 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,20 +17,6 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -VERSION_NAME=1.4 -VERSION_CODE=14 -GROUP=me.gujun.android.taggroup - -POM_DESCRIPTION=Android Library to display a set of tags -POM_URL=https://github.com/2dxgujun/AndroidTagGroup -POM_SCM_URL=https://github.com/2dxgujun/AndroidTagGroup -POM_SCM_CONNECTION=scm:https://github.com/2dxgujun/AndroidTagGroup.git -POM_SCM_DEV_CONNECTION=scm:https://github.com/2dxgujun/AndroidTagGroup.git -POM_LICENCE_NAME=The Apache Software License, Version 2.0 -POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt -POM_LICENCE_DIST=repo -POM_DEVELOPER_ID=2dxgujun -POM_DEVELOPER_NAME=Jun Gu - -SNAPSHOT_REPOSITORY_URL=https://oss.sonatype.org/content/repositories/snapshots -RELEASE_REPOSITORY_URL=https://oss.sonatype.org/service/local/staging/deploy/maven2 \ No newline at end of file +VERSION_NAME=1.7.3 +VERSION_CODE=18 +GROUP=me.gujun.android.taggroup \ No newline at end of file diff --git a/library/build.gradle b/library/build.gradle index 87bfd43..158a74c 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -1,18 +1,28 @@ apply plugin: 'com.android.library' + android { - compileSdkVersion 21 - buildToolsVersion '21.1.1' + compileSdkVersion 23 + buildToolsVersion "23.0.2" + defaultConfig { minSdkVersion 8 - targetSdkVersion 21 + targetSdkVersion 23 + versionCode 1 + versionName "1.0" } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + // Travis CI needing lintOptions { abortOnError false } - productFlavors { - } } -// Used to push in maven -apply from: '../maven-push.gradle' + dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + compile 'com.android.support:support-annotations:23.2.1' } \ No newline at end of file diff --git a/library/src/main/java/me/gujun/android/taggroup/TagGroup.java b/library/src/main/java/me/gujun/android/taggroup/AndroidTagGroup.java similarity index 62% rename from library/src/main/java/me/gujun/android/taggroup/TagGroup.java rename to library/src/main/java/me/gujun/android/taggroup/AndroidTagGroup.java index 5f2ae99..1307f98 100644 --- a/library/src/main/java/me/gujun/android/taggroup/TagGroup.java +++ b/library/src/main/java/me/gujun/android/taggroup/AndroidTagGroup.java @@ -12,7 +12,9 @@ import android.graphics.RectF; import android.os.Parcel; import android.os.Parcelable; +import android.support.annotation.ColorInt; import android.text.Editable; +import android.text.InputType; import android.text.TextUtils; import android.text.TextWatcher; import android.text.method.ArrowKeyMovementMethod; @@ -49,146 +51,231 @@ * @version 2.0 * @since 2015-2-3 14:16:32 */ -public class TagGroup extends ViewGroup { - private final int default_border_color = Color.rgb(0x49, 0xC1, 0x20); - private final int default_text_color = Color.rgb(0x49, 0xC1, 0x20); - private final int default_background_color = Color.WHITE; - private final int default_dash_border_color = Color.rgb(0xAA, 0xAA, 0xAA); - private final int default_input_hint_color = Color.argb(0x80, 0x00, 0x00, 0x00); - private final int default_input_text_color = Color.argb(0xDE, 0x00, 0x00, 0x00); - private final int default_checked_border_color = Color.rgb(0x49, 0xC1, 0x20); - private final int default_checked_text_color = Color.WHITE; - private final int default_checked_marker_color = Color.WHITE; - private final int default_checked_background_color = Color.rgb(0x49, 0xC1, 0x20); - private final int default_pressed_background_color = Color.rgb(0xED, 0xED, 0xED); - private final float default_border_stroke_width; - private final float default_text_size; - private final float default_horizontal_spacing; - private final float default_vertical_spacing; - private final float default_horizontal_padding; - private final float default_vertical_padding; - - /** Indicates whether this TagGroup is set up to APPEND mode or DISPLAY mode. Default is false. */ - private boolean isAppendMode; +public class AndroidTagGroup extends ViewGroup { + private final int DEFAULT_BORDER_COLOR = Color.rgb(0x49, 0xC1, 0x20); + private final int DEFAULT_TEXT_COLOR = Color.rgb(0x49, 0xC1, 0x20); + private final int DEFAULT_BACKGROUND_COLOR = Color.WHITE; + private final int DEFAULT_DASH_BORDER_COLOR = Color.rgb(0xAA, 0xAA, 0xAA); + private final int DEFAULT_INPUT_HINT_COLOR = Color.argb(0x80, 0x00, 0x00, 0x00); + private final int DEFAULT_INPUT_TEXT_COLOR = Color.argb(0xDE, 0x00, 0x00, 0x00); + private final int DEFAULT_CHECKED_BORDER_COLOR = Color.rgb(0x49, 0xC1, 0x20); + private final int DEFAULT_CHECKED_TEXT_COLOR = Color.WHITE; + private final int DEFAULT_CHECKED_MARKER_COLOR = Color.WHITE; + private final int DEFAULT_CHECKED_BACKGROUND_COLOR = Color.rgb(0x49, 0xC1, 0x20); + private final int DEFAULT_PRESSED_BACKGROUND_COLOR = Color.rgb(0xED, 0xED, 0xED); + private final float mDefaultBorderStrokeWidth; + private final float mDefaultTextSize; + private final float mDefaultHorizontalSpacing; + private final float mDefaultVerticalSpacing; + private final float mDefaultHorizontalPadding; + private final float mDefaultVerticalPadding; + // Characters limitation (Default: no limitation) + private int mCharsLimitation = -1; + // Indicates whether this TagGroup is set up to APPEND mode or DISPLAY mode. Default is false. + private boolean mIsAppendMode; + // The text to be displayed when the text of the INPUT tag is empty. + private CharSequence mInputHint; + @ColorInt + // The tag outline border color. + private int mBorderColor; + @ColorInt + // The tag text color. + private int mTextColor; + @ColorInt + // The tag background color. + private int mBackgroundColor; + @ColorInt + // The dash outline border color. + private int mDashBorderColor; + @ColorInt + // The input tag hint text color. + private int mInputHintColor; + @ColorInt + // The input tag type text color. + private int mInputTextColor; + @ColorInt + // The checked tag outline border color. + private int mCheckedBorderColor; + @ColorInt + // The check text color + private int mCheckedTextColor; + @ColorInt + // The checked marker color. + private int mCheckedMarkerColor; + @ColorInt + // The checked tag background color. + private int mCheckedBackgroundColor; + @ColorInt + // The tag background color, when the tag is being pressed. + private int mPressedBackgroundColor; + // The tag outline border stroke width, default is 0.5dp. + private float mBorderStrokeWidth; + // The tag text size, default is 13sp. + private float mTextSize; + // The horizontal tag spacing, default is 8.0dp. + private int mHorizontalSpacing; + // The vertical tag spacing, default is 4.0dp. + private int mVerticalSpacing; + // The horizontal tag padding, default is 12.0dp. + private int mHorizontalPadding; + // The vertical tag padding, default is 3.0dp. + private int mVerticalPadding; + // Listener used to dispatch tag change event. + private OnTagChangeListener mOnTagChangeListener; + private OnTagLimitationExceedListener mOnTagLimitationExceedListener; + // Listener used to dispatch tag click event. + private OnTagClickListener mOnTagClickListener; + // Adding tags limitation. + private int mTagsLimitation = -1; + // Listener used to handle tag click event. + private InternalTagClickListener mInternalTagClickListener = new InternalTagClickListener(); - /** The text to be displayed when the text of the INPUT tag is empty. */ - private CharSequence inputHint; + public AndroidTagGroup(Context context) { + this(context, null); + } - /** The tag outline border color. */ - private int borderColor; + public AndroidTagGroup(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.tagGroupStyle); + } - /** The tag text color. */ - private int textColor; + public AndroidTagGroup(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mDefaultBorderStrokeWidth = AndroidUtils.dp2px(getContext(), 0.5f); + mDefaultTextSize = AndroidUtils.sp2px(getContext(), 13.0f); + mDefaultHorizontalSpacing = AndroidUtils.dp2px(getContext(), 8.0f); + mDefaultVerticalSpacing = AndroidUtils.dp2px(getContext(), 4.0f); + mDefaultHorizontalPadding = AndroidUtils.dp2px(getContext(), 12.0f); + mDefaultVerticalPadding = AndroidUtils.dp2px(getContext(), 3.0f); - /** The tag background color. */ - private int backgroundColor; + // Load styled attributes. + final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AndroidTagGroup, defStyleAttr, R.style.AndroidTagGroup); + try { + mIsAppendMode = typedArray.getBoolean(R.styleable.AndroidTagGroup_atg_isAppendMode, false); + mInputHint = typedArray.getText(R.styleable.AndroidTagGroup_atg_inputHint); + mBorderColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_borderColor, DEFAULT_BORDER_COLOR); + mTextColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_textColor, DEFAULT_TEXT_COLOR); + mBackgroundColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_backgroundColor, DEFAULT_BACKGROUND_COLOR); + mDashBorderColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_dashBorderColor, DEFAULT_DASH_BORDER_COLOR); + mInputHintColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_inputHintColor, DEFAULT_INPUT_HINT_COLOR); + mInputTextColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_inputTextColor, DEFAULT_INPUT_TEXT_COLOR); + mCheckedBorderColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_checkedBorderColor, DEFAULT_CHECKED_BORDER_COLOR); + mCheckedTextColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_checkedTextColor, DEFAULT_CHECKED_TEXT_COLOR); + mCheckedMarkerColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_checkedMarkerColor, DEFAULT_CHECKED_MARKER_COLOR); + mCheckedBackgroundColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_checkedBackgroundColor, DEFAULT_CHECKED_BACKGROUND_COLOR); + mPressedBackgroundColor = typedArray.getColor(R.styleable.AndroidTagGroup_atg_pressedBackgroundColor, DEFAULT_PRESSED_BACKGROUND_COLOR); + mBorderStrokeWidth = typedArray.getDimension(R.styleable.AndroidTagGroup_atg_borderStrokeWidth, mDefaultBorderStrokeWidth); + mTextSize = typedArray.getDimension(R.styleable.AndroidTagGroup_atg_textSize, mDefaultTextSize); + mHorizontalSpacing = (int) typedArray.getDimension(R.styleable.AndroidTagGroup_atg_horizontalSpacing, mDefaultHorizontalSpacing); + mVerticalSpacing = (int) typedArray.getDimension(R.styleable.AndroidTagGroup_atg_verticalSpacing, mDefaultVerticalSpacing); + mHorizontalPadding = (int) typedArray.getDimension(R.styleable.AndroidTagGroup_atg_horizontalPadding, mDefaultHorizontalPadding); + mVerticalPadding = (int) typedArray.getDimension(R.styleable.AndroidTagGroup_atg_verticalPadding, mDefaultVerticalPadding); + mTagsLimitation = typedArray.getInteger(R.styleable.AndroidTagGroup_atg_tagsLimitation, -1); + mCharsLimitation = typedArray.getInteger(R.styleable.AndroidTagGroup_atg_charsLimitation, -1); + } finally { + typedArray.recycle(); + } - /** The dash outline border color. */ - private int dashBorderColor; + if (mIsAppendMode) { + // Append the initial INPUT tag. + appendInputTag(); - /** The input tag hint text color. */ - private int inputHintColor; + // Set the click listener to detect the end-input event. + setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + submitTag(); + } + }); + } + } - /** The input tag type text color. */ - private int inputTextColor; + public void setAppendMode(boolean appendMode) { + mIsAppendMode = appendMode; + } - /** The checked tag outline border color. */ - private int checkedBorderColor; + public void setInputHint(CharSequence inputHint) { + mInputHint = inputHint; + } - /** The check text color */ - private int checkedTextColor; + public void setBorderColor(@ColorInt int borderColor) { + mBorderColor = borderColor; + } - /** The checked marker color. */ - private int checkedMarkerColor; + public void setTextColor(@ColorInt int textColor) { + mTextColor = textColor; + } - /** The checked tag background color. */ - private int checkedBackgroundColor; + public void setViewBackgroundColor(@ColorInt int backgroundColor) { + mBackgroundColor = backgroundColor; + } - /** The tag background color, when the tag is being pressed. */ - private int pressedBackgroundColor; + public void setDashBorderColor(@ColorInt int dashBorderColor) { + mDashBorderColor = dashBorderColor; + } - /** The tag outline border stroke width, default is 0.5dp. */ - private float borderStrokeWidth; + public void setInputHintColor(@ColorInt int inputHintColor) { + mInputHintColor = inputHintColor; + } - /** The tag text size, default is 13sp. */ - private float textSize; + public void setInputTextColor(@ColorInt int inputTextColor) { + mInputTextColor = inputTextColor; + } - /** The horizontal tag spacing, default is 8.0dp. */ - private int horizontalSpacing; + public void setCheckedBorderColor(@ColorInt int checkedBorderColor) { + mCheckedBorderColor = checkedBorderColor; + } - /** The vertical tag spacing, default is 4.0dp. */ - private int verticalSpacing; + public void setCheckedTextColor(@ColorInt int checkedTextColor) { + mCheckedTextColor = checkedTextColor; + } - /** The horizontal tag padding, default is 12.0dp. */ - private int horizontalPadding; + public void setCheckedMarkerColor(@ColorInt int checkedMarkerColor) { + mCheckedMarkerColor = checkedMarkerColor; + } - /** The vertical tag padding, default is 3.0dp. */ - private int verticalPadding; + public void setCheckedBackgroundColor(@ColorInt int checkedBackgroundColor) { + mCheckedBackgroundColor = checkedBackgroundColor; + } - /** Listener used to dispatch tag change event. */ - private OnTagChangeListener mOnTagChangeListener; + public void setPressedBackgroundColor(@ColorInt int pressedBackgroundColor) { + mPressedBackgroundColor = pressedBackgroundColor; + } - /** Listener used to dispatch tag click event. */ - private OnTagClickListener mOnTagClickListener; + public void setBorderStrokeWidth(float borderStrokeWidth) { + mBorderStrokeWidth = borderStrokeWidth; + } - /** Listener used to handle tag click event. */ - private InternalTagClickListener mInternalTagClickListener = new InternalTagClickListener(); + public void setTextSize(float textSize) { + mTextSize = textSize; + } - public TagGroup(Context context) { - this(context, null); + public void setHorizontalSpacing(int horizontalSpacing) { + mHorizontalSpacing = horizontalSpacing; } - public TagGroup(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.tagGroupStyle); + public void setVerticalSpacing(int verticalSpacing) { + mVerticalSpacing = verticalSpacing; } - public TagGroup(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - default_border_stroke_width = dp2px(0.5f); - default_text_size = sp2px(13.0f); - default_horizontal_spacing = dp2px(8.0f); - default_vertical_spacing = dp2px(4.0f); - default_horizontal_padding = dp2px(12.0f); - default_vertical_padding = dp2px(3.0f); + public void setHorizontalPadding(int horizontalPadding) { + mHorizontalPadding = horizontalPadding; + } - // Load styled attributes. - final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TagGroup, defStyleAttr, R.style.TagGroup); - try { - isAppendMode = a.getBoolean(R.styleable.TagGroup_atg_isAppendMode, false); - inputHint = a.getText(R.styleable.TagGroup_atg_inputHint); - borderColor = a.getColor(R.styleable.TagGroup_atg_borderColor, default_border_color); - textColor = a.getColor(R.styleable.TagGroup_atg_textColor, default_text_color); - backgroundColor = a.getColor(R.styleable.TagGroup_atg_backgroundColor, default_background_color); - dashBorderColor = a.getColor(R.styleable.TagGroup_atg_dashBorderColor, default_dash_border_color); - inputHintColor = a.getColor(R.styleable.TagGroup_atg_inputHintColor, default_input_hint_color); - inputTextColor = a.getColor(R.styleable.TagGroup_atg_inputTextColor, default_input_text_color); - checkedBorderColor = a.getColor(R.styleable.TagGroup_atg_checkedBorderColor, default_checked_border_color); - checkedTextColor = a.getColor(R.styleable.TagGroup_atg_checkedTextColor, default_checked_text_color); - checkedMarkerColor = a.getColor(R.styleable.TagGroup_atg_checkedMarkerColor, default_checked_marker_color); - checkedBackgroundColor = a.getColor(R.styleable.TagGroup_atg_checkedBackgroundColor, default_checked_background_color); - pressedBackgroundColor = a.getColor(R.styleable.TagGroup_atg_pressedBackgroundColor, default_pressed_background_color); - borderStrokeWidth = a.getDimension(R.styleable.TagGroup_atg_borderStrokeWidth, default_border_stroke_width); - textSize = a.getDimension(R.styleable.TagGroup_atg_textSize, default_text_size); - horizontalSpacing = (int) a.getDimension(R.styleable.TagGroup_atg_horizontalSpacing, default_horizontal_spacing); - verticalSpacing = (int) a.getDimension(R.styleable.TagGroup_atg_verticalSpacing, default_vertical_spacing); - horizontalPadding = (int) a.getDimension(R.styleable.TagGroup_atg_horizontalPadding, default_horizontal_padding); - verticalPadding = (int) a.getDimension(R.styleable.TagGroup_atg_verticalPadding, default_vertical_padding); - } finally { - a.recycle(); - } + public void setVerticalPadding(int verticalPadding) { + mVerticalPadding = verticalPadding; + } - if (isAppendMode) { - // Append the initial INPUT tag. - appendInputTag(); + /** + * Register a callback to be invoked when limitation exceed. + * + * @param onTagLimitationExceedListener + */ + public void setOnTagLimitationExceedListener(OnTagLimitationExceedListener onTagLimitationExceedListener) { + mOnTagLimitationExceedListener = onTagLimitationExceedListener; + } - // Set the click listener to detect the end-input event. - setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - submitTag(); - } - }); - } + public void setCharsLimitation(int limitation) { + mCharsLimitation = limitation; } /** @@ -200,12 +287,165 @@ public void submitTag() { inputTag.endInput(); if (mOnTagChangeListener != null) { - mOnTagChangeListener.onAppend(TagGroup.this, inputTag.getText().toString()); + mOnTagChangeListener.onAppend(AndroidTagGroup.this, inputTag.getText().toString()); } appendInputTag(); } } + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + final int parentLeft = getPaddingLeft(); + final int parentRight = r - l - getPaddingRight(); + final int parentTop = getPaddingTop(); + + int childLeft = parentLeft; + int childTop = parentTop; + + int rowMaxHeight = 0; + + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + final int width = child.getMeasuredWidth(); + final int height = child.getMeasuredHeight(); + + if (child.getVisibility() != GONE) { + if (childLeft + width > parentRight) { // Next line + childLeft = parentLeft; + childTop += rowMaxHeight + mVerticalSpacing; + rowMaxHeight = height; + } else { + rowMaxHeight = Math.max(rowMaxHeight, height); + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + + childLeft += width + mHorizontalSpacing; + } + } + } + + @Override + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + /** + * Return the last NORMAL state tag view in this group. + * + * @return the last NORMAL state tag view or null if not exists + */ + protected TagView getLastNormalTagView() { + final int lastNormalTagIndex = mIsAppendMode ? getChildCount() - 2 : getChildCount() - 1; + return getTagAt(lastNormalTagIndex); + } + + /** + * Returns the tag view at the specified position in the group. + * + * @param index the position at which to get the tag view from. + * @return the tag view at the specified position or null if the position + * does not exists within this group. + */ + protected TagView getTagAt(int index) { + return (TagView) getChildAt(index); + } + + /** + * Returns the checked tag view in the group. + * + * @return the checked tag view or null if not exists. + */ + protected TagView getCheckedTag() { + final int checkedTagIndex = getCheckedTagIndex(); + if (checkedTagIndex != -1) { + return getTagAt(checkedTagIndex); + } + return null; + } + + /** + * Return the checked tag index. + * + * @return the checked tag index, or -1 if not exists. + */ + protected int getCheckedTagIndex() { + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final TagView tag = getTagAt(i); + if (tag.isChecked) { + return i; + } + } + return -1; + } + + /** + * Register a callback to be invoked when this tag group is changed. + * + * @param l the callback that will run + */ + public void setOnTagChangeListener(OnTagChangeListener l) { + mOnTagChangeListener = l; + } + + public void setTagsLimitation(int tagsLimitation) { + this.mTagsLimitation = tagsLimitation; + } + + /** + * Register a callback to be invoked when a tag is clicked. + * + * @param l the callback that will run. + */ + public void setOnTagClickListener(OnTagClickListener l) { + mOnTagClickListener = l; + } + + protected void deleteTag(TagView tagView) { + removeView(tagView); + if (mOnTagChangeListener != null) { + mOnTagChangeListener.onDelete(AndroidTagGroup.this, tagView.getText().toString()); + } + if (getInputTag().mState == TagView.STATE_INPUT) { + if (!getInputTag().isEnabled()) { + getInputTag().setEnabled(true); + } + } + } + + /** + * Returns the INPUT tag view in this group. + * + * @return the INPUT state tag view or null if not exists + */ + protected TagView getInputTag() { + if (mIsAppendMode) { + final int inputTagIndex = getChildCount() - 1; + final TagView inputTag = getTagAt(inputTagIndex); + if (inputTag != null && inputTag.mState == TagView.STATE_INPUT) { + return inputTag; + } else { + return null; + } + } else { + return null; + } + } + + /** + * Returns the INPUT state tag in this group. + * + * @return the INPUT state tag view or null if not exists + */ + public String getInputTagText() { + final TagView inputTagView = getInputTag(); + if (inputTagView != null) { + return inputTagView.getText().toString(); + } + return null; + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int widthMode = MeasureSpec.getMode(widthMeasureSpec); @@ -215,7 +455,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { measureChildren(widthMeasureSpec, heightMeasureSpec); - int width = 0; + int width; int height = 0; int row = 0; // The row counter. @@ -232,13 +472,13 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { rowWidth += childWidth; if (rowWidth > widthSize) { // Next line. rowWidth = childWidth; // The next row width. - height += rowMaxHeight + verticalSpacing; + height += rowMaxHeight + mVerticalSpacing; rowMaxHeight = childHeight; // The next row max height. row++; } else { // This line. rowMaxHeight = Math.max(rowMaxHeight, childHeight); } - rowWidth += horizontalSpacing; + rowWidth += mHorizontalSpacing; } } // Account for the last row height. @@ -259,39 +499,6 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { heightMode == MeasureSpec.EXACTLY ? heightSize : height); } - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - final int parentLeft = getPaddingLeft(); - final int parentRight = r - l - getPaddingRight(); - final int parentTop = getPaddingTop(); - final int parentBottom = b - t - getPaddingBottom(); - - int childLeft = parentLeft; - int childTop = parentTop; - - int rowMaxHeight = 0; - - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - final int width = child.getMeasuredWidth(); - final int height = child.getMeasuredHeight(); - - if (child.getVisibility() != GONE) { - if (childLeft + width > parentRight) { // Next line - childLeft = parentLeft; - childTop += rowMaxHeight + verticalSpacing; - rowMaxHeight = height; - } else { - rowMaxHeight = Math.max(rowMaxHeight, height); - } - child.layout(childLeft, childTop, childLeft + width, childTop + height); - - childLeft += width + horizontalSpacing; - } - } - } - @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); @@ -324,49 +531,6 @@ public void onRestoreInstanceState(Parcelable state) { } } - /** - * Returns the INPUT tag view in this group. - * - * @return the INPUT state tag view or null if not exists - */ - protected TagView getInputTag() { - if (isAppendMode) { - final int inputTagIndex = getChildCount() - 1; - final TagView inputTag = getTagAt(inputTagIndex); - if (inputTag != null && inputTag.mState == TagView.STATE_INPUT) { - return inputTag; - } else { - return null; - } - } else { - return null; - } - } - - /** - * Returns the INPUT state tag in this group. - * - * @return the INPUT state tag view or null if not exists - */ - public String getInputTagText() { - final TagView inputTagView = getInputTag(); - if (inputTagView != null) { - return inputTagView.getText().toString(); - } - return null; - } - - /** - * Return the last NORMAL state tag view in this group. - * - * @return the last NORMAL state tag view or null if not exists - */ - protected TagView getLastNormalTagView() { - final int lastNormalTagIndex = isAppendMode ? getChildCount() - 2 : getChildCount() - 1; - TagView lastNormalTagView = getTagAt(lastNormalTagIndex); - return lastNormalTagView; - } - /** * Returns the tag array in group, except the INPUT tag. * @@ -398,65 +562,19 @@ public void setTags(List tagList) { * @param tags the tag list to set. */ public void setTags(String... tags) { + if (mTagsLimitation != -1 && tags.length > mTagsLimitation) { + throw new IllegalStateException(String.format("There is a limitation (%1$d) in adding tags.", mTagsLimitation)); + } removeAllViews(); for (final String tag : tags) { appendTag(tag); } - if (isAppendMode) { + if (mIsAppendMode) { appendInputTag(); } } - /** - * Returns the tag view at the specified position in the group. - * - * @param index the position at which to get the tag view from. - * @return the tag view at the specified position or null if the position - * does not exists within this group. - */ - protected TagView getTagAt(int index) { - return (TagView) getChildAt(index); - } - - /** - * Returns the checked tag view in the group. - * - * @return the checked tag view or null if not exists. - */ - protected TagView getCheckedTag() { - final int checkedTagIndex = getCheckedTagIndex(); - if (checkedTagIndex != -1) { - return getTagAt(checkedTagIndex); - } - return null; - } - - /** - * Return the checked tag index. - * - * @return the checked tag index, or -1 if not exists. - */ - protected int getCheckedTagIndex() { - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - final TagView tag = getTagAt(i); - if (tag.isChecked) { - return i; - } - } - return -1; - } - - /** - * Register a callback to be invoked when this tag group is changed. - * - * @param l the callback that will run - */ - public void setOnTagChangeListener(OnTagChangeListener l) { - mOnTagChangeListener = l; - } - /** * @see #appendInputTag(String) */ @@ -472,10 +590,40 @@ protected void appendInputTag() { protected void appendInputTag(String tag) { final TagView previousInputTag = getInputTag(); if (previousInputTag != null) { - throw new IllegalStateException("Already has a INPUT tag in group."); + throw new IllegalStateException("Already has an INPUT tag in group."); } final TagView newInputTag = new TagView(getContext(), TagView.STATE_INPUT, tag); + + if (mCharsLimitation != -1) { + newInputTag.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (getInputTagText().length() - 1 == mCharsLimitation) { + newInputTag.setText(getInputTagText().substring(0, mCharsLimitation)); + newInputTag.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)); + } + } + }); + } + + // If limitation exceed, disable the input and invoke a callback. + if (mTagsLimitation != -1 && getTags().length >= mTagsLimitation) { + if (mOnTagLimitationExceedListener != null) { + mOnTagLimitationExceedListener.onLimitationExceed(); + } + newInputTag.setEnabled(false); + } newInputTag.setOnClickListener(mInternalTagClickListener); addView(newInputTag); } @@ -491,36 +639,17 @@ protected void appendTag(CharSequence tag) { addView(newTag); } - public float dp2px(float dp) { - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, - getResources().getDisplayMetrics()); - } - - public float sp2px(float sp) { - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, - getResources().getDisplayMetrics()); - } - - @Override - public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { - return new TagGroup.LayoutParams(getContext(), attrs); - } /** - * Register a callback to be invoked when a tag is clicked. - * - * @param l the callback that will run. + * Interface definition for a callback to be invoked when adding tags limitation exceed. */ - public void setOnTagClickListener(OnTagClickListener l) { - mOnTagClickListener = l; + public interface OnTagLimitationExceedListener { + /** + * Called when limitation exceed. + */ + void onLimitationExceed(); } - protected void deleteTag(TagView tagView) { - removeView(tagView); - if (mOnTagChangeListener != null) { - mOnTagChangeListener.onDelete(TagGroup.this, tagView.getText().toString()); - } - } /** * Interface definition for a callback to be invoked when a tag group is changed. @@ -531,16 +660,17 @@ public interface OnTagChangeListener { * * @param tag the appended tag. */ - void onAppend(TagGroup tagGroup, String tag); + void onAppend(AndroidTagGroup androidTagGroup, String tag); /** * Called when a tag has been deleted from the the group. * * @param tag the deleted tag. */ - void onDelete(TagGroup tagGroup, String tag); + void onDelete(AndroidTagGroup androidTagGroup, String tag); } + /** * Interface definition for a callback to be invoked when a tag is clicked. */ @@ -554,20 +684,7 @@ public interface OnTagClickListener { } /** - * Per-child layout information for layouts. - */ - public static class LayoutParams extends ViewGroup.LayoutParams { - public LayoutParams(Context c, AttributeSet attrs) { - super(c, attrs); - } - - public LayoutParams(int width, int height) { - super(width, height); - } - } - - /** - * For {@link TagGroup} save and restore state. + * For {@link AndroidTagGroup} save and restore state. */ static class SavedState extends BaseSavedState { public static final Parcelable.Creator CREATOR = @@ -616,7 +733,7 @@ class InternalTagClickListener implements OnClickListener { @Override public void onClick(View v) { final TagView tag = (TagView) v; - if (isAppendMode) { + if (mIsAppendMode) { if (tag.mState == TagView.STATE_INPUT) { // If the clicked tag is in INPUT state, uncheck the previous checked tag if exists. final TagView checkedTag = getCheckedTag(); @@ -652,19 +769,29 @@ class TagView extends TextView { public static final int STATE_NORMAL = 1; public static final int STATE_INPUT = 2; - /** The offset to the text. */ + /** + * The offset to the text. + */ private static final int CHECKED_MARKER_OFFSET = 3; - /** The stroke width of the checked marker */ + /** + * The stroke width of the checked marker + */ private static final int CHECKED_MARKER_STROKE_WIDTH = 4; - /** The current state. */ + /** + * The current state. + */ private int mState; - /** Indicates the tag if checked. */ + /** + * Indicates the tag if checked. + */ private boolean isChecked = false; - /** Indicates the tag if pressed. */ + /** + * Indicates the tag if pressed. + */ private boolean isPressed = false; private Paint mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -673,57 +800,73 @@ class TagView extends TextView { private Paint mCheckedMarkerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - /** The rect for the tag's left corner drawing. */ + /** + * The rect for the tag's left corner drawing. + */ private RectF mLeftCornerRectF = new RectF(); - /** The rect for the tag's right corner drawing. */ + /** + * The rect for the tag's right corner drawing. + */ private RectF mRightCornerRectF = new RectF(); - /** The rect for the tag's horizontal blank fill area. */ + /** + * The rect for the tag's horizontal blank fill area. + */ private RectF mHorizontalBlankFillRectF = new RectF(); - /** The rect for the tag's vertical blank fill area. */ + /** + * The rect for the tag's vertical blank fill area. + */ private RectF mVerticalBlankFillRectF = new RectF(); - /** The rect for the checked mark draw bound. */ + /** + * The rect for the checked mark draw bound. + */ private RectF mCheckedMarkerBound = new RectF(); - /** Used to detect the touch event. */ + /** + * Used to detect the touch event. + */ private Rect mOutRect = new Rect(); - /** The path for draw the tag's outline border. */ + /** + * The path for draw the tag's outline border. + */ private Path mBorderPath = new Path(); - /** The path effect provide draw the dash border. */ + /** + * The path effect provide draw the dash border. + */ private PathEffect mPathEffect = new DashPathEffect(new float[]{10, 5}, 0); { mBorderPaint.setStyle(Paint.Style.STROKE); - mBorderPaint.setStrokeWidth(borderStrokeWidth); + mBorderPaint.setStrokeWidth(mBorderStrokeWidth); mBackgroundPaint.setStyle(Paint.Style.FILL); mCheckedMarkerPaint.setStyle(Paint.Style.FILL); mCheckedMarkerPaint.setStrokeWidth(CHECKED_MARKER_STROKE_WIDTH); - mCheckedMarkerPaint.setColor(checkedMarkerColor); + mCheckedMarkerPaint.setColor(mCheckedMarkerColor); } public TagView(Context context, final int state, CharSequence text) { super(context); - setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding); - setLayoutParams(new TagGroup.LayoutParams( - TagGroup.LayoutParams.WRAP_CONTENT, - TagGroup.LayoutParams.WRAP_CONTENT)); + setPadding(mHorizontalPadding, mVerticalPadding, mHorizontalPadding, mVerticalPadding); + setLayoutParams(new LayoutParams( + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT)); setGravity(Gravity.CENTER); setText(text); - setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); + setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); mState = state; - setClickable(isAppendMode); + setClickable(mIsAppendMode); setFocusable(state == STATE_INPUT); setFocusableInTouchMode(state == STATE_INPUT); - setHint(state == STATE_INPUT ? inputHint : null); + setHint(state == STATE_INPUT ? mInputHint : null); setMovementMethod(state == STATE_INPUT ? ArrowKeyMovementMethod.getInstance() : null); // Interrupted long click event to avoid PAUSE popup. @@ -736,6 +879,9 @@ public boolean onLongClick(View v) { if (state == STATE_INPUT) { requestFocus(); + //Replace Enter (new line) button with Action Go + setRawInputType(InputType.TYPE_CLASS_TEXT); + setImeOptions(EditorInfo.IME_ACTION_GO); // Handle the ENTER key down. setOnEditorActionListener(new OnEditorActionListener() { @@ -749,7 +895,7 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { // the event, then append a new INPUT state tag. endInput(); if (mOnTagChangeListener != null) { - mOnTagChangeListener.onAppend(TagGroup.this, getText().toString()); + mOnTagChangeListener.onAppend(AndroidTagGroup.this, getText().toString()); } appendInputTag(); } @@ -771,7 +917,7 @@ public boolean onKey(View v, int keyCode, KeyEvent event) { if (lastNormalTagView.isChecked) { removeView(lastNormalTagView); if (mOnTagChangeListener != null) { - mOnTagChangeListener.onDelete(TagGroup.this, lastNormalTagView.getText().toString()); + mOnTagChangeListener.onDelete(AndroidTagGroup.this, lastNormalTagView.getText().toString()); } } else { final TagView checkedTagView = getCheckedTag(); @@ -813,19 +959,12 @@ public void afterTextChanged(Editable s) { } /** - * Set whether this tag view is in the checked state. + * Indicates whether the input content is available. * - * @param checked true is checked, false otherwise + * @return True if the input content is available, false otherwise. */ - public void setChecked(boolean checked) { - isChecked = checked; - // Make the checked mark drawing region. - setPadding(horizontalPadding, - verticalPadding, - isChecked ? (int) (horizontalPadding + getHeight() / 2.5f + CHECKED_MARKER_OFFSET) - : horizontalPadding, - verticalPadding); - invalidatePaint(); + public boolean isInputAvailable() { + return getText() != null && getText().length() > 0; } /** @@ -845,51 +984,58 @@ public void endInput() { requestLayout(); } - @Override - protected boolean getDefaultEditable() { - return true; - } - /** - * Indicates whether the input content is available. + * Set whether this tag view is in the checked state. * - * @return True if the input content is available, false otherwise. + * @param checked true is checked, false otherwise */ - public boolean isInputAvailable() { - return getText() != null && getText().length() > 0; + public void setChecked(boolean checked) { + isChecked = checked; + // Make the checked mark drawing region. + setPadding(mHorizontalPadding, + mVerticalPadding, + isChecked ? (int) (mHorizontalPadding + getHeight() / 2.5f + CHECKED_MARKER_OFFSET) + : mHorizontalPadding, + mVerticalPadding); + invalidatePaint(); } private void invalidatePaint() { - if (isAppendMode) { + if (mIsAppendMode) { if (mState == STATE_INPUT) { - mBorderPaint.setColor(dashBorderColor); + mBorderPaint.setColor(mDashBorderColor); mBorderPaint.setPathEffect(mPathEffect); - mBackgroundPaint.setColor(backgroundColor); - setHintTextColor(inputHintColor); - setTextColor(inputTextColor); + mBackgroundPaint.setColor(mBackgroundColor); + setHintTextColor(mInputHintColor); + setTextColor(mInputTextColor); } else { mBorderPaint.setPathEffect(null); if (isChecked) { - mBorderPaint.setColor(checkedBorderColor); - mBackgroundPaint.setColor(checkedBackgroundColor); - setTextColor(checkedTextColor); + mBorderPaint.setColor(mCheckedBorderColor); + mBackgroundPaint.setColor(mCheckedBackgroundColor); + setTextColor(mCheckedTextColor); } else { - mBorderPaint.setColor(borderColor); - mBackgroundPaint.setColor(backgroundColor); - setTextColor(textColor); + mBorderPaint.setColor(mBorderColor); + mBackgroundPaint.setColor(mBackgroundColor); + setTextColor(mTextColor); } } } else { - mBorderPaint.setColor(borderColor); - mBackgroundPaint.setColor(backgroundColor); - setTextColor(textColor); + mBorderPaint.setColor(mBorderColor); + mBackgroundPaint.setColor(mBackgroundColor); + setTextColor(mTextColor); } if (isPressed) { - mBackgroundPaint.setColor(pressedBackgroundColor); + mBackgroundPaint.setColor(mPressedBackgroundColor); } } + @Override + protected boolean getDefaultEditable() { + return true; + } + @Override protected void onDraw(Canvas canvas) { canvas.drawArc(mLeftCornerRectF, -180, 90, true, mBackgroundPaint); @@ -912,13 +1058,60 @@ protected void onDraw(Canvas canvas) { super.onDraw(canvas); } + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + /* + Following line returns null if the view is not enabled + We need to check if the returned value is null or not because of enabling or disabling the input view for + have the limitation feature. + */ + InputConnection inputConnection = super.onCreateInputConnection(outAttrs); + if (inputConnection != null) { + return new ZanyInputConnection(super.onCreateInputConnection(outAttrs), true); + } + return null; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mState == STATE_INPUT) { + // The INPUT tag doesn't change background color on the touch event. + return super.onTouchEvent(event); + } + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + getDrawingRect(mOutRect); + isPressed = true; + invalidatePaint(); + invalidate(); + break; + } + case MotionEvent.ACTION_MOVE: { + if (!mOutRect.contains((int) event.getX(), (int) event.getY())) { + isPressed = false; + invalidatePaint(); + invalidate(); + } + break; + } + case MotionEvent.ACTION_UP: { + isPressed = false; + invalidatePaint(); + invalidate(); + break; + } + } + return super.onTouchEvent(event); + } + @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); - int left = (int) borderStrokeWidth; - int top = (int) borderStrokeWidth; - int right = (int) (left + w - borderStrokeWidth * 2); - int bottom = (int) (top + h - borderStrokeWidth * 2); + int left = (int) mBorderStrokeWidth; + int top = (int) mBorderStrokeWidth; + int right = (int) (left + w - mBorderStrokeWidth * 2); + int bottom = (int) (top + h - mBorderStrokeWidth * 2); int d = bottom - top; @@ -949,58 +1142,20 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { int m = (int) (h / 2.5f); h = bottom - top; - mCheckedMarkerBound.set(right - m - horizontalPadding + CHECKED_MARKER_OFFSET, + mCheckedMarkerBound.set(right - m - mHorizontalPadding + CHECKED_MARKER_OFFSET, top + h / 2 - m / 2, - right - horizontalPadding + CHECKED_MARKER_OFFSET, + right - mHorizontalPadding + CHECKED_MARKER_OFFSET, bottom - h / 2 + m / 2); // Ensure the checked mark drawing region is correct across screen orientation changes. if (isChecked) { - setPadding(horizontalPadding, - verticalPadding, - (int) (horizontalPadding + h / 2.5f + CHECKED_MARKER_OFFSET), - verticalPadding); + setPadding(mHorizontalPadding, + mVerticalPadding, + (int) (mHorizontalPadding + h / 2.5f + CHECKED_MARKER_OFFSET), + mVerticalPadding); } } - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mState == STATE_INPUT) { - // The INPUT tag doesn't change background color on the touch event. - return super.onTouchEvent(event); - } - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: { - getDrawingRect(mOutRect); - isPressed = true; - invalidatePaint(); - invalidate(); - break; - } - case MotionEvent.ACTION_MOVE: { - if (!mOutRect.contains((int) event.getX(), (int) event.getY())) { - isPressed = false; - invalidatePaint(); - invalidate(); - } - break; - } - case MotionEvent.ACTION_UP: { - isPressed = false; - invalidatePaint(); - invalidate(); - break; - } - } - return super.onTouchEvent(event); - } - - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - return new ZanyInputConnection(super.onCreateInputConnection(outAttrs), true); - } - /** * Solve edit text delete(backspace) key detect, see * Android: Backspace in WebView/BaseInputConnection @@ -1020,6 +1175,13 @@ public boolean deleteSurroundingText(int beforeLength, int afterLength) { } return super.deleteSurroundingText(beforeLength, afterLength); } + + @Override + public boolean sendKeyEvent(KeyEvent event) { + return super.sendKeyEvent(event); + } } } + + } \ No newline at end of file diff --git a/library/src/main/java/me/gujun/android/taggroup/AndroidUtils.java b/library/src/main/java/me/gujun/android/taggroup/AndroidUtils.java new file mode 100644 index 0000000..450d0b8 --- /dev/null +++ b/library/src/main/java/me/gujun/android/taggroup/AndroidUtils.java @@ -0,0 +1,19 @@ +package me.gujun.android.taggroup; + +import android.content.Context; +import android.util.TypedValue; + +/** + * Created by Alireza Eskandarpour Shoferi on 12/22/2015. + */ +public class AndroidUtils { + public static float dp2px(Context context, float dp) { + return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, + context.getResources().getDisplayMetrics()); + } + + public static float sp2px(Context context, float sp) { + return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, + context.getResources().getDisplayMetrics()); + } +} diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 3cf9b16..0dc6f4e 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -1,48 +1,50 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + + + - + \ No newline at end of file diff --git a/library/src/main/res/values/styles.xml b/library/src/main/res/values/styles.xml index 416e530..811d6e3 100644 --- a/library/src/main/res/values/styles.xml +++ b/library/src/main/res/values/styles.xml @@ -1,7 +1,7 @@ - - - - -