HashtagView


Source link: https://github.com/greenfrvr/hashtag-view

HashtagView

Version 1.3.1 available!

Fully customizable widget for representing data like hashtags collection and similiar.

Demo

Downlaod latest demo app from Play Market:

Gradle Dependency

Easily reference the library in your Android projects using this dependency in your module's build.gradle file:

dependencies {

  compile 'com.github.greenfrvr:hashtag-view:1.3.1' 
}

or

dependencies {

  compile ('com.github.greenfrvr:hashtag-view:1.3.1@aar'){

transitive=true
  
}
 
}

Library available on both jCenter and Maven Central, but in case of any issues (library can't be resolved) use Bintray repo.

Add repository to your app's build.gradle file:

repositories {

  maven {

url 'https://dl.bintray.com/greenfrvr/maven/'
  
}
 
}

This will reference Bintray's Maven repository that contains hashtags widget directly, rather than going through jCenter first.

Data

First of all there are three ways to fill HashtagView with data.

  1. If you need only displaying your data you can use HashtagView.setData(List<String> data); method.
  2. If you want some more complex behavior or you want to use your data models, then you can use HashtagViewsetData(List<T> list, DataTransform<T> transformer) method.
    First you setting up some items collection, then you're telling how you want to display your data using DataTransform interface. For example you have model
public class Person {

  int id;
  String firstName;
  String midName
  String lastName; 
}

Now when passing list of Person's, we implementing DataTransform interface

HashtagView.setData(persons, new HashtagView.DataTransform<Person>() {

 @Override

 public CharSequence prepare(Person item) {

  String label = "@" + item.firstName.getCharAt(0) + item.midName.getCharAt(0) + item.lastName;

  SpannableString spannableString = new SpannableString(label);

  spannableString.setSpan(new SuperscriptSpan(), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

  spannableString.setSpan(new ForegroundColorSpan(color1), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

  spannableString.setSpan(new ForegroundColorSpan(color2), 1, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

  return spannableString;

 
}
 
}
);

As you may notice implementing DataTransform.prepare() method let you define Spannable representation of each item.
To retrieve list of all data items call HashtagView.getData().
3. If you use widget in selectionMode and you want some items to be preselected, then you can use HashtagViewsetData(List<T> list, DataTransform<T> transformer, DataSelector<T> selector) method.
This method works just like previous one, but additional interface DataSelector allows you to specify which items should be in selected state, before user can select something. For example to select each second item it can be implemented like this:

HashtagView.setData(persons, transformer, new HashtagView.DataSelector<Person>() {

 @Override

 public boolean preselect(Person item) {

  return persons.indexOf(item) % 2 == 1;

 
}
 
}
);

Notice that items won't be preselected if widget is not in selectionMode.
Also while in selectionMode you can use HashtagView.DataStateTransform instead of HashtagView.DataTransform. DataStateTransform allows you to define how your items will be displayed in selected state, for example you can define different Spannable representations for selected and non-selected states. (Take a look at "styles sample" in demo app)

HashtagView.DataTransform<String> stateTransform = new HashtagView.DataStateTransform<String>() {

 @Override

 public CharSequence prepare(Person item) {

  String label = "@" + item.firstName.getCharAt(0) + item.midName.getCharAt(0) + item.lastName;

  SpannableString spannableString = new SpannableString(label);

  spannableString.setSpan(new SuperscriptSpan(), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

  spannableString.setSpan(new ForegroundColorSpan(color1), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

  spannableString.setSpan(new ForegroundColorSpan(color2), 1, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

  return spannableString;

 
}

 @Override

 public CharSequence prepareSelected(Person item) {

  String label = "@" + item.firstName.getCharAt(0) + item.midName.getCharAt(0) + item.lastName;

  SpannableString spannableString = new SpannableString(label);

  spannableString.setSpan(new SuperscriptSpan(), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

  spannableString.setSpan(new ForegroundColorSpan(color1), 0, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

  spannableString.setSpan(new StrikethroughSpan(), 1, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

  return spannableString;

 
}
 
}
;

You can limit amount of selected items at a time by calling setSelectionLimit(int limit); method. Setting value to zero or less than zero will remove selection limit.

Customizing

All attributes can be defined in layout .xml file or programmatically. Below is a list of available attributes.

Text attributes
 <!-- Item text color. -->
  <attr name="tagTextColor" format="color"/>
  <!-- Item text size. -->
  <attr name="tagTextSize" format="dimension"/>
  <!-- Item text gravity, works only in stretch mode. -->
  <attr name="tagTextGravity" format="enum">

<enum name="left" value="3"/>

<enum name="right" value="5"/>

<enum name="center" value="17"/>
  </attr>
  <!-- Item text ellipsize mode (just like in TextView). -->
  <attr name="tagEllipsize" format="enum">

<enum name="start" value="0"/>

<enum name="middle" value="1"/>

<enum name="end" value="2"/>

<enum name="marquee" value="3"/>
  </attr>
Background and drawables
 <!-- Item background color or resource. -->
  <attr name="tagBackground" format="color|reference"/>
  <!-- Item foreground color or resource. -->
  <attr name="tagForeground" format="color|reference"/>
  <!-- Item left drawable resource. -->
  <attr name="tagDrawableLeft" format="reference"/>
  <!-- Item selected state left drawable resource. -->
  <attr name="tagSelectedDrawableLeft" format="reference"/>
  <!-- Item right drawable resource. -->
  <attr name="tagDrawableRight" format="reference"/>
  <!-- Item selected state right drawable resource. -->
  <attr name="tagSelectedDrawableRight" format="reference"/>
  <!-- Item drawable padding. -->
  <attr name="tagDrawablePadding" format="dimension"/>
Spacing
 <!-- Item left and right margins, total distance between two items in a row is be 2 * tagMergin. -->
  <attr name="tagMargin" format="dimension"/>
  <!-- Item left padding. -->
  <attr name="tagPaddingLeft" format="dimension"/>
  <!-- Item right padding. -->
  <attr name="tagPaddingRight" format="dimension"/>
  <!-- Item top padding. -->
  <attr name="tagPaddingTop" format="dimension"/>
  <!-- Item bottom padding. -->
  <attr name="tagPaddingBottom" format="dimension"/>
  <!-- Item minimal width. -->
  <attr name="tagMinWidth" format="dimension"/>
  <!-- Item maximal width. -->
  <attr name="tagMaxWidth" format="dimension"/>
  <!-- Row top and bottom margins, total distance between two rows is 2 * rowMargin. -->
  <attr name="rowMargin" format="dimension"/>
Specific properties
 <!-- Defines gravity of row items distribution. -->
  <attr name="rowGravity" format="enum">

<enum name="left" value="3"/>

<enum name="right" value="5"/>

<enum name="center" value="17"/>
  </attr>
  <!-- Defines row items distribution based on items weight. -->
  <attr name="rowDistribution" format="enum">

<enum name="left" value="0"/>

<enum name="middle" value="1"/>

<enum name="right" value="2"/>

<enum name="random" value="3"/>

<enum name="none" value="4"/>
  </attr>
  <!-- Defines if each item will wrap its content, or widget will fill all given width. -->
  <attr name="rowMode" format="enum">

<enum name="wrap" value="0"/>

<enum name="stretch" value="1"/>

<enum name="equal" value="2"/>
  </attr>
  <!-- Defines fixed rows quantity, can be considered as horizontal mode (require HorizontalScrollView wrapping)-->
  <attr name="rowsQuantity" format="integer"/>
  <!-- Enables selection mode (don't forget to use <selectors>). -->
  <attr name="selectionMode" format="boolean"/>
  <!-- Enables dynamic mode (allows to add/remove items dynamically). -->
  <attr name="dynamicMode" format="boolean"/>
  <!-- Changes items positioning implementation algorythm. -->
  <attr name="composeMode" format="enum">

<enum name="origin" value="0"/>

<enum name="linear" value="1"/>
  </attr>

Also you can set up custom typeface by HashtagView.setTypeface(Typeface). If you want to use some <selector> backgrounds you can set tagBackground property, tagForeground property can be used in case if you want to use <ripple> drawables.

Events

There are two type of events that can be handled by HashtagView.

  • Item click event.

Setting up item click listener

HashtagView.addOnTagClickListener(new HashtagView.TagsClickListener() {

 @Override

 public void onItemClicked(Object item) {

  Person p = (Person) item;

 
}
 
}
);
  • Item selection event.

Setting up item selection listener. From version 1.1.1 selection callback is returning selection state for exact item, i.e. it returns data model and its selection state, true - for selected state, false - for non-selected.

HashtagView.addOnTagSelectListener(new HashtagView.TagsSelectListener() {

 @Override

 public void onItemSelected(Object item, boolean selected) {

  Person p = (Person) item;

 
}
 
}
);

Both callbacks returns object of corresponding type defined in HashtagView.setData() method. To get list of all selected items call HashtagView.getSelectedItems(). Also only one listener can be used at a time, i.e. if widget is in selectionMode then HashtagView.TagsSelectListener will handle click events, but not HashtagView.TagsClickListener.

All listeners implemented using Observer pattern, so you can set multiple listeners for both types of events. To remove some specific listener use HashtagView.removeOnTagClickListener(TagsClickListener listener) or HashtagView.removeOnTagSelectListener(TagsSelectListener listener) or you can remove all available listeners by calling HashtagView.removeListeners(). Note: be attentive and do not let listener to remove itself.

Dynamic mode

To be able add and remove tags dynamically you should set dynamic mode to true (via code or xml). After that you can use next methods:

  • HastagView.addItem() returns true if item added successfully, false if item can't be added (in case HastagView already contains such item)
  • HastagView.removeItem() returns true if item removed successfully, false if item can't be removed (in case HashtagView doesn't contain such item)

Distribution mode

Distribution mode is responsible for sorting items by width inside each row. There are 5 different distribution modes available:

  • RowDistribution.DISTRIBUTION_LEFT wider items are on the left side of a row
  • RowDistribution.DISTRIBUTION_MIDDLE wider items are in the middle of a row
  • RowDistribution.DISTRIBUTION_RIGHT wider items are on the right side of a row
  • RowDistribution.DISTRIBUTION_RANDOM items are placed randomly inside a row
  • RowDistribution.DISTRIBUTION_NONE no sorting is applied

Default distribution mode is DISTRIBUTION_NONE. You can change it either via xml attributes or programmatically.

Compose mode

There are 2 different implementations of item positioning algorythms available:

  • Compose.COMPOSE_ORIGIN represents implementation of versions 1.2.1 and below. The idea of that implementation is to make all rows look even. It is achieved by sorting items by single item views width and putting items to rows according to greedy algorithm. This compose mode will change order of incoming items.
  • Compose.COMPOSE_LINEAR is available since version 1.3.0 implementation. It puts items in a row one by one until row is fullfiled, then next rows will be filled by the same rule. Using this compose mode with RowDistribution.DISTRIBUTION_NONE distribution option saves incoming items order as is.

Default compose mode is COMPOSE_ORIGIN. You can change it either via xml attributes or programmatically.

Resources

AndroidPhotoFilters aims to provide fast, powerful and flexible image processing instrument for creating awesome effects on any image media.
Android choosing image from camera or gallery with Crop functionality
???? A basic sample android application to understand MVP in a very simple way. Just clone, build, run and understand MVP.
Pull or Swipe to Refresh Webview
Simple clock view for displaying uh...time?
Custom toasts with color and icon for Android.

Topics


2D Engines   3D Engines   9-Patch   Action Bars   Activities   ADB   Advertisements   Analytics   Animations   ANR   AOP   API   APK   APT   Architecture   Audio   Autocomplete   Background Processing   Backward Compatibility   Badges   Bar Codes   Benchmarking   Bitmaps   Bluetooth   Blur Effects   Bread Crumbs   BRMS   Browser Extensions   Build Systems   Bundles   Buttons   Caching   Camera   Canvas   Cards   Carousels   Changelog   Checkboxes   Cloud Storages   Color Analysis   Color Pickers   Colors   Comet/Push   Compass Sensors   Conferences   Content Providers   Continuous Integration   Crash Reports   Credit Cards   Credits   CSV   Curl/Flip   Data Binding   Data Generators   Data Structures   Database   Database Browsers   Date &   Debugging   Decompilers   Deep Links   Dependency Injections   Design   Design Patterns   Dex   Dialogs   Distributed Computing   Distribution Platforms   Download Managers   Drawables   Emoji   Emulators   EPUB   Equalizers &   Event Buses   Exception Handling   Face Recognition   Feedback &   File System   File/Directory   Fingerprint   Floating Action   Fonts   Forms   Fragments   FRP   FSM   Functional Programming   Gamepads   Games   Geocaching   Gestures   GIF   Glow Pad   Gradle Plugins   Graphics   Grid Views   Highlighting   HTML   HTTP Mocking   Icons   IDE   IDE Plugins   Image Croppers   Image Loaders   Image Pickers   Image Processing   Image Views   Instrumentation   Intents   Job Schedulers   JSON   Keyboard   Kotlin   Layouts   Library Demos   List View   List Views   Localization   Location   Lock Patterns   Logcat   Logging   Mails   Maps   Markdown   Mathematics   Maven Plugins   MBaaS   Media   Menus   Messaging   MIME   Mobile Web   Native Image   Navigation   NDK   Networking   NFC   NoSQL   Number Pickers   OAuth   Object Mocking   OCR Engines   OpenGL   ORM   Other Pickers   Parallax List   Parcelables   Particle Systems   Password Inputs   PDF   Permissions   Physics Engines   Platforms   Plugin Frameworks   Preferences   Progress Indicators   ProGuard   Properties   Protocol Buffer   Pull To   Purchases   Push/Pull   QR Codes   Quick Return   Radio Buttons   Range Bars   Ratings   Recycler Views   Resources   REST   Ripple Effects   RSS   Screenshots   Scripting   Scroll Views   SDK   Search Inputs   Security   Sensors   Services   Showcase Views   Signatures   Sliding Panels   Snackbars   SOAP   Social Networks   Spannable   Spinners   Splash Screens   SSH   Static Analysis   Status Bars   Styling   SVG   System   Tags   Task Managers   TDD &   Template Engines   Testing   Testing Tools   Text Formatting   Text Views   Text Watchers   Text-to   Toasts   Toolkits For   Tools   Tooltips   Trainings   TV   Twitter   Updaters   USB   User Stories   Utils   Validation   Video   View Adapters   View Pagers   Views   Watch Face   Wearable Data   Wearables   Weather   Web Tools   Web Views   WebRTC   WebSockets   Wheel Widgets   Wi-Fi   Widgets   Windows   Wizards   XML   XMPP   YAML   ZIP Codes