diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser new file mode 100644 index 0000000..cdf9785 Binary files /dev/null and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..0d15693 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+
+
\ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..d1ec78b --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a5f05cd --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..37a7509 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..05b07f3 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/HashTagHelper.zip b/HashTagHelper.zip new file mode 100644 index 0000000..8ad0295 Binary files /dev/null and b/HashTagHelper.zip differ diff --git a/README.md b/README.md index 7558ad6..69d2472 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# HashTagHelper +# HashTagHelper - Android HashTag This is a library designed for highlighting hashtags ("#example") and catching click on them. [![Android_weekly](https://img.shields.io/badge/Android%20Weekly-HashTagHelper-green.svg)](http://androidweekly.net/issues/issue-185) @@ -17,7 +17,7 @@ Add this snippet to your module build.gradle file: ``` dependencies { - compile 'com.github.danylovolokh:hashtag-helper:1.1.0' + implementation 'com.github.immujahidkhan:HashTagHelper:1.1.1' } ``` Getting click events and highligthing hashtags. @@ -70,6 +70,7 @@ List allHashTags = mTextHashTagHelper.getAllHashTags(true); List allHashTags = mTextHashTagHelper.getAllHashTags(false); ``` #Demo +``` ![alt tag](https://cloud.githubusercontent.com/assets/2686355/11998408/e6aa1f62-aaa6-11e5-911a-c598b6853862.gif) ![alt tag](https://cloud.githubusercontent.com/assets/2686355/11998409/e6aa3ed4-aaa6-11e5-9797-100a024659cc.gif) # License diff --git a/build.gradle b/build.gradle index e0b366a..9f0b959 100644 --- a/build.gradle +++ b/build.gradle @@ -3,18 +3,17 @@ buildscript { repositories { jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:1.5.0' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files + classpath "com.android.tools.build:gradle:4.0.1" } } allprojects { repositories { jcenter() + google() } } diff --git a/gradle.properties b/gradle.properties index 1d3591c..c52ac9b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,18 +1,19 @@ # Project-wide Gradle settings. - # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. - # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html - # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - +org.gradle.jvmargs=-Xmx2048m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f23df6e..4dcd73b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Oct 21 11:34:03 PDT 2015 +#Sun Aug 16 14:44:08 PKT 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip \ No newline at end of file diff --git a/hashtag-helper/build.gradle b/hashtag-helper/build.gradle index e331317..1cf7840 100644 --- a/hashtag-helper/build.gradle +++ b/hashtag-helper/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 23 - buildToolsVersion "21.1.2" + compileSdkVersion 30 + buildToolsVersion "30.0.0" defaultConfig { minSdkVersion 15 - targetSdkVersion 23 + targetSdkVersion 30 versionCode 1 versionName "1.1" } @@ -19,7 +19,9 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - testCompile 'junit:junit:4.12' - compile 'com.android.support:appcompat-v7:23.1.1' + implementation fileTree(dir: "libs", include: ["*.jar"]) + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'androidx.appcompat:appcompat:1.2.0' } diff --git a/hashtag-helper/src/main/java/com/volokh/danylo/hashtaghelper/ClickableForegroundColorSpan.java b/hashtag-helper/src/main/java/com/volokh/danylo/hashtaghelper/ClickableForegroundColorSpan.java index cbba84a..20fa258 100644 --- a/hashtag-helper/src/main/java/com/volokh/danylo/hashtaghelper/ClickableForegroundColorSpan.java +++ b/hashtag-helper/src/main/java/com/volokh/danylo/hashtaghelper/ClickableForegroundColorSpan.java @@ -1,12 +1,13 @@ package com.volokh.danylo.hashtaghelper; -import android.support.annotation.ColorInt; import android.text.Spanned; import android.text.TextPaint; import android.text.style.ClickableSpan; import android.view.View; import android.widget.TextView; +import androidx.annotation.ColorInt; + /** * Created by danylo.volokh on 12/22/2015. * This class is a combination of {@link android.text.style.ForegroundColorSpan} @@ -18,8 +19,8 @@ public class ClickableForegroundColorSpan extends ClickableSpan { private OnHashTagClickListener mOnHashTagClickListener; - public interface OnHashTagClickListener { - void onHashTagClicked(String hashTag); + public interface OnHashTagClickListener { + void onHashTagClicked(T hashTag); } private final int mColor; diff --git a/hashtag-helper/src/main/java/com/volokh/danylo/hashtaghelper/HashTagHelper.java b/hashtag-helper/src/main/java/com/volokh/danylo/hashtaghelper/HashTagHelper.java index a3062dc..6f56d3b 100644 --- a/hashtag-helper/src/main/java/com/volokh/danylo/hashtaghelper/HashTagHelper.java +++ b/hashtag-helper/src/main/java/com/volokh/danylo/hashtaghelper/HashTagHelper.java @@ -17,12 +17,11 @@ /** * This is a helper class that should be used with {@link android.widget.EditText} or {@link android.widget.TextView} * In order to have hash-tagged words highlighted. It also provides a click listeners for every hashtag - * + *

* Example : * #ThisIsHashTagWord * #ThisIsFirst#ThisIsSecondHashTag * #hashtagendsifitfindsnotletterornotdigitsignlike_thisIsNotHighlithedArea - * */ public final class HashTagHelper implements ClickableForegroundColorSpan.OnHashTagClickListener { @@ -31,9 +30,8 @@ public final class HashTagHelper implements ClickableForegroundColorSpan.OnHashT * For example : * mAdditionalHashTagChars = {'$','_','-'} * it means that hashtag: "#this_is_hashtag-with$dollar-sign" will be highlighted. - * + *

* Note: if mAdditionalHashTagChars would be "null" only "#this" would be highlighted - * */ private final List mAdditionalHashTagChars; private TextView mTextView; @@ -41,22 +39,24 @@ public final class HashTagHelper implements ClickableForegroundColorSpan.OnHashT private OnHashTagClickListener mOnHashTagClickListener; - public static final class Creator{ - private Creator(){} + public static final class Creator { - public static HashTagHelper create(int color, OnHashTagClickListener listener){ + private Creator() { + } + + public static HashTagHelper create(int color, OnHashTagClickListener listener) { return new HashTagHelper(color, listener, null); } - public static HashTagHelper create(int color, OnHashTagClickListener listener, char... additionalHashTagChars){ + public static HashTagHelper create(int color, OnHashTagClickListener listener, char... additionalHashTagChars) { return new HashTagHelper(color, listener, additionalHashTagChars); } } - public interface OnHashTagClickListener{ - void onHashTagClicked(String hashTag); + public interface OnHashTagClickListener { + void onHashTagClicked(T hashTag); } private final TextWatcher mTextWatcher = new TextWatcher() { @@ -81,22 +81,22 @@ private HashTagHelper(int color, OnHashTagClickListener listener, char... additi mOnHashTagClickListener = listener; mAdditionalHashTagChars = new ArrayList<>(); - if(additionalHashTagCharacters != null){ - for(char additionalChar : additionalHashTagCharacters){ + if (additionalHashTagCharacters != null) { + for (char additionalChar : additionalHashTagCharacters) { mAdditionalHashTagChars.add(additionalChar); } } } - public void handle(TextView textView){ - if(mTextView == null){ + public void handle(TextView textView) { + if (mTextView == null) { mTextView = textView; mTextView.addTextChangedListener(mTextWatcher); // in order to use spannable we have to set buffer type mTextView.setText(mTextView.getText(), TextView.BufferType.SPANNABLE); - if(mOnHashTagClickListener != null){ + if (mOnHashTagClickListener != null) { // we need to set this in order to get onClick event mTextView.setMovementMethod(LinkMovementMethod.getInstance()); @@ -130,10 +130,10 @@ private void setColorsToAllHashTags(CharSequence text) { int startIndexOfNextHashSign; int index = 0; - while (index < text.length()- 1){ + while (index < text.length() - 1) { char sign = text.charAt(index); int nextNotLetterDigitCharIndex = index + 1; // we assume it is next. if if was not changed by findNextValidHashTagChar then index will be incremented by 1 - if(sign == '#'){ + if (sign == '#') { startIndexOfNextHashSign = index; nextNotLetterDigitCharIndex = findNextValidHashTagChar(text, startIndexOfNextHashSign); @@ -171,7 +171,7 @@ private void setColorForHashTagToTheEnd(int startIndex, int nextNotLetterDigitCh CharacterStyle span; - if(mOnHashTagClickListener != null){ + if (mOnHashTagClickListener != null) { span = new ClickableForegroundColorSpan(mHashTagWordColor, this); } else { // no need for clickable span because it is messing with selection when click @@ -192,8 +192,8 @@ public List getAllHashTags(boolean withHashes) { for (CharacterStyle span : spannable.getSpans(0, text.length(), CharacterStyle.class)) { hashTags.add( text.substring(!withHashes ? spannable.getSpanStart(span) + 1/*skip "#" sign*/ - : spannable.getSpanStart(span), - spannable.getSpanEnd(span))); + : spannable.getSpanStart(span), + spannable.getSpanEnd(span))); } return new ArrayList<>(hashTags); @@ -203,8 +203,9 @@ public List getAllHashTags() { return getAllHashTags(false); } + @Override - public void onHashTagClicked(String hashTag) { + public void onHashTagClicked(Object hashTag) { mOnHashTagClickListener.onHashTagClicked(hashTag); } } diff --git a/sample_app/build.gradle b/sample_app/build.gradle index 6d68191..bd23b5e 100644 --- a/sample_app/build.gradle +++ b/sample_app/build.gradle @@ -1,13 +1,12 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 23 - buildToolsVersion "21.1.2" - + compileSdkVersion 30 + buildToolsVersion "30.0.0" defaultConfig { applicationId "com.volokh.danylo.hashtaghelper" minSdkVersion 15 - targetSdkVersion 23 + targetSdkVersion 30 versionCode 1 versionName "1.0" } @@ -20,8 +19,10 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - testCompile 'junit:junit:4.12' - compile 'com.android.support:appcompat-v7:23.1.1' + implementation fileTree(dir: "libs", include: ["*.jar"]) + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'androidx.appcompat:appcompat:1.2.0' compile project(':hashtag-helper') } diff --git a/sample_app/src/main/AndroidManifest.xml b/sample_app/src/main/AndroidManifest.xml index af78368..820484d 100644 --- a/sample_app/src/main/AndroidManifest.xml +++ b/sample_app/src/main/AndroidManifest.xml @@ -8,9 +8,9 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> - + diff --git a/sample_app/src/main/java/com/volokh/danylo/example/HashTagHelperDemoActivity.java b/sample_app/src/main/java/com/volokh/danylo/example/HashTagHelperDemoActivity.java index f90782f..c5cf386 100644 --- a/sample_app/src/main/java/com/volokh/danylo/example/HashTagHelperDemoActivity.java +++ b/sample_app/src/main/java/com/volokh/danylo/example/HashTagHelperDemoActivity.java @@ -1,6 +1,5 @@ package com.volokh.danylo.example; -import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; @@ -8,6 +7,8 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.appcompat.app.AppCompatActivity; + import com.volokh.danylo.hashtaghelper.HashTagHelper; import java.util.List; @@ -56,7 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { @Override public void onHashTagClicked(String hashTag) { Log.v(TAG, "onHashTagClicked [" + hashTag + "]"); - if(mToast != null){ + if (mToast != null) { mToast.cancel(); } mToast = Toast.makeText(HashTagHelperDemoActivity.this, hashTag, Toast.LENGTH_SHORT); @@ -65,7 +66,7 @@ public void onHashTagClicked(String hashTag) { @Override public void onClick(View v) { - switch (v.getId()){ + switch (v.getId()) { case R.id.get_entered_text_btn: mHashTagText.setText(mEditTextView.getText()); break;