├── .gitignore ├── README.md ├── build.gradle ├── demo ├── .gitignore ├── build.gradle ├── proguard-rules.txt └── src │ └── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ └── info │ │ └── hoang8f │ │ └── mymo │ │ └── segmented │ │ └── demo │ │ ├── SampleActivity.java │ │ └── SampleApplication.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── layout │ ├── activity_sample.xml │ ├── fragment_sample.xml │ └── radio_button_item.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── gradle.properties ├── proguard-rules.txt └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── fontawesome-webfont.ttf │ ├── java │ └── info │ │ └── hoang8f │ │ └── android │ │ └── segmented │ │ ├── AwesomeRadioButton.java │ │ ├── SegmentedGroup.java │ │ ├── font │ │ ├── AwesomeTypefaceSpan.java │ │ ├── BootstrapTextView.java │ │ ├── FontAwesome.java │ │ └── IconSet.java │ │ └── utils │ │ ├── BootstrapText.java │ │ ├── IconResolver.java │ │ └── TypefaceProvider.java │ └── res │ ├── drawable │ ├── button_text_color.xml │ ├── radio_checked.xml │ └── radio_unchecked.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── maven_push.gradle ├── screenshot ├── screenshot.png ├── screenshot2.png └── screenshot3.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 4 | 5 | *.iml 6 | 7 | ## Directory-based project format: 8 | .idea/ 9 | # if you remove the above rule, at least ignore the following: 10 | 11 | # User-specific stuff: 12 | # .idea/workspace.xml 13 | # .idea/tasks.xml 14 | # .idea/dictionaries 15 | 16 | # Sensitive or high-churn files: 17 | # .idea/dataSources.ids 18 | # .idea/dataSources.xml 19 | # .idea/sqlDataSources.xml 20 | # .idea/dynamic.xml 21 | # .idea/uiDesigner.xml 22 | 23 | # Gradle: 24 | # .idea/gradle.xml 25 | # .idea/libraries 26 | 27 | # Mongo Explorer plugin: 28 | # .idea/mongoSettings.xml 29 | 30 | ## File-based project format: 31 | *.ipr 32 | *.iws 33 | 34 | ## Plugin-specific files: 35 | 36 | # IntelliJ 37 | /out/ 38 | 39 | # mpeltonen/sbt-idea plugin 40 | .idea_modules/ 41 | 42 | # JIRA plugin 43 | atlassian-ide-plugin.xml 44 | 45 | # Crashlytics plugin (for Android Studio and IntelliJ) 46 | com_crashlytics_export_strings.xml 47 | crashlytics.properties 48 | crashlytics-build.properties 49 | ### Android template 50 | # Built application files 51 | *.apk 52 | *.ap_ 53 | 54 | # Files for the Dalvik VM 55 | *.dex 56 | 57 | # Java class files 58 | *.class 59 | 60 | # Generated files 61 | bin/ 62 | gen/ 63 | 64 | # Gradle files 65 | .gradle/ 66 | build/ 67 | 68 | # Local configuration file (sdk path, etc) 69 | local.properties 70 | 71 | # Proguard folder generated by Eclipse 72 | proguard/ 73 | 74 | # Log Files 75 | *.log 76 | 77 | # Android Studio Navigation editor temp files 78 | .navigation/ 79 | 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | android-segmented-control 2 | ========================= 3 | Android-Segmented is a custom view for Android which is based on RadioGroup and RadioButton widget. 4 | This implementation is inspired by [Segmented Controls](https://developer.apple.com/library/ios/documentation/userexperience/conceptual/UIKitUICatalog/UISegmentedControl.html) for iOS. 5 | 6 | 7 | ![Sample Image](https://raw.githubusercontent.com/hoang8f/android-segmented-control/master/screenshot/screenshot3.png) 8 | 9 | ## Including in your project: 10 | 11 | #### Download source code and import as module 12 | The latest code has bug fixes, iOS 7's (and up) style segment control (which has nice fade animation and tint) and support for Font Awesome. (These features has not been pushed to Maven yet) 13 | 14 | #### Using maven 15 | Android-Segmented Library is pushed to [Maven Central](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22android-segmented%22), so you just need to add the following dependency to your `build.gradle`. 16 | 17 | dependencies { 18 | compile 'info.hoang8f:android-segmented:1.0.6' 19 | } 20 | 21 | #### Manually 22 | Copy(or merge) below files into corresponding file/folder: 23 | + SegmentedGroup.java 24 | + res/drawable/* 25 | + res/drawable-v14/* 26 | + res/values/colors.xml 27 | + res/values/dimens.xml 28 | + res/values/styles.xml (only RadioButton style) 29 | 30 | Usage 31 | ----- 32 | Define in xml like this and make sure that the `RadioButton`'s style is: `@style/RadioButton` 33 | 34 | ```xml 35 | 36 | 37 | 38 | 39 | ``` 40 | 41 | Sample code: 42 | ```xml 43 | 44 | 53 | 54 | 60 | 61 | 67 | 68 | ``` 69 | 70 | You also can be change the tint color and title color when button is checked by `setTintColor` method. 71 | Here is sample code: 72 | 73 | ```java 74 | SegmentedGroup segmented2 = (SegmentedGroup) rootView.findViewById(R.id.segmented2); 75 | segmented2.setTintColor(Color.DKGRAY); 76 | 77 | SegmentedGroup segmented3 = (SegmentedGroup) rootView.findViewById(R.id.segmented3); 78 | segmented3.setTintColor(Color.parseColor("#FFD0FF3C"), Color.parseColor("#FF7B07B2")); 79 | 80 | SegmentedGroup segmented4 = (SegmentedGroup) rootView.findViewById(R.id.segmented4); 81 | segmented4.setTintColor(getResources().getColor(R.color.radio_button_selected_color)); 82 | ``` 83 | If you dont specify border_width and/or corner_radius the default values will be used (1dp for border_width and 5 dp for corner_radius) 84 | 85 | Credits 86 | ------- 87 | Author: 88 | * Le Van Hoang (@hoang8f) 89 | * Added support for vertical RadioGroup by [tchar](https://github.com/tchar). 90 | 91 | License 92 | ------- 93 | The MIT License (MIT) 94 | 95 | Copyright (c) 2014 Le Van Hoang 96 | 97 | Permission is hereby granted, free of charge, to any person obtaining a copy 98 | of this software and associated documentation files (the "Software"), to deal 99 | in the Software without restriction, including without limitation the rights 100 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 101 | copies of the Software, and to permit persons to whom the Software is 102 | furnished to do so, subject to the following conditions: 103 | 104 | The above copyright notice and this permission notice shall be included in all 105 | copies or substantial portions of the Software. 106 | 107 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 108 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 109 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 110 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 111 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 112 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 113 | SOFTWARE. 114 | 115 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | mavenCentral() 6 | maven { 7 | url "https://oss.sonatype.org/content/repositories/snapshots" 8 | } 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:1.5.0' 12 | } 13 | } 14 | 15 | def isReleaseBuild() { 16 | return version.contains("SNAPSHOT") == false 17 | } 18 | 19 | allprojects { 20 | version = VERSION_NAME 21 | group = GROUP 22 | 23 | repositories { 24 | mavenCentral() 25 | maven { 26 | url "https://oss.sonatype.org/content/repositories/snapshots" 27 | } 28 | } 29 | } 30 | 31 | apply plugin: 'android-reporting' 32 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /demo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion '23.0.2' 6 | defaultConfig { 7 | minSdkVersion 8 8 | targetSdkVersion 23 9 | versionCode 1 10 | versionName '1.0' 11 | } 12 | buildTypes { 13 | release { 14 | minifyEnabled false 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 16 | } 17 | } 18 | productFlavors { 19 | } 20 | } 21 | 22 | dependencies { 23 | compile 'com.android.support:appcompat-v7:23.1.1' 24 | compile fileTree(dir: 'libs', include: ['*.jar']) 25 | compile project(':library') 26 | // compile 'info.hoang8f:android-segmented:1.0.6' 27 | } 28 | -------------------------------------------------------------------------------- /demo/proguard-rules.txt: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the ProGuard 5 | # include property in project.properties. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} -------------------------------------------------------------------------------- /demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /demo/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kaopiz/android-segmented-control/519e553c84a351929d4ef2fdf31854e3a36735b9/demo/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /demo/src/main/java/info/hoang8f/mymo/segmented/demo/SampleActivity.java: -------------------------------------------------------------------------------- 1 | package info.hoang8f.mymo.segmented.demo; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.support.v7.app.ActionBarActivity; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.Button; 11 | import android.widget.RadioButton; 12 | import android.widget.RadioGroup; 13 | import android.widget.Toast; 14 | 15 | import info.hoang8f.android.segmented.AwesomeRadioButton; 16 | import info.hoang8f.android.segmented.SegmentedGroup; 17 | 18 | public class SampleActivity extends AppCompatActivity { 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_sample); 24 | 25 | if (savedInstanceState == null) { 26 | getSupportFragmentManager().beginTransaction() 27 | .add(R.id.container, new PlaceholderFragment()) 28 | .commit(); 29 | } 30 | } 31 | 32 | /** 33 | * A placeholder fragment containing a simple view. 34 | */ 35 | public static class PlaceholderFragment extends Fragment implements RadioGroup.OnCheckedChangeListener, View.OnClickListener { 36 | 37 | SegmentedGroup segmented5; 38 | 39 | public PlaceholderFragment() { 40 | } 41 | 42 | @Override 43 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 44 | Bundle savedInstanceState) { 45 | View rootView = inflater.inflate(R.layout.fragment_sample, container, false); 46 | 47 | // SegmentedGroup segmented2 = (SegmentedGroup) rootView.findViewById(R.id.segmented2); 48 | // segmented2.setTintColor(Color.DKGRAY); 49 | // 50 | // SegmentedGroup segmented3 = (SegmentedGroup) rootView.findViewById(R.id.segmented3); 51 | // //Tint color, and text color when checked 52 | //// segmented3.setTintColor(Color.parseColor("#FFD0FF3C"), Color.parseColor("#FF7B07B2")); 53 | // 54 | 55 | segmented5 = (SegmentedGroup) rootView.findViewById(R.id.segmented5); 56 | Button addBtn = (Button) rootView.findViewById(R.id.add_segmented); 57 | Button removeBtn = (Button) rootView.findViewById(R.id.remove_segmented); 58 | 59 | //Set listener for button 60 | addBtn.setOnClickListener(this); 61 | removeBtn.setOnClickListener(this); 62 | 63 | //Set change listener on SegmentedGroup 64 | // segmented2.setOnCheckedChangeListener(this); 65 | // segmented3.setOnCheckedChangeListener(this); 66 | segmented5.setOnCheckedChangeListener(this); 67 | 68 | // Support awesome font 69 | AwesomeRadioButton button = (AwesomeRadioButton) rootView.findViewById(R.id.button42); 70 | button.setMarkdownText("{fa_facebook} facebook"); 71 | return rootView; 72 | } 73 | 74 | @Override 75 | public void onCheckedChanged(RadioGroup group, int checkedId) { 76 | switch (checkedId) { 77 | case R.id.button21: 78 | Toast.makeText(getActivity(), "One", Toast.LENGTH_SHORT).show(); 79 | break; 80 | case R.id.button22: 81 | Toast.makeText(getActivity(), "Two", Toast.LENGTH_SHORT).show(); 82 | break; 83 | case R.id.button31: 84 | Toast.makeText(getActivity(), "One", Toast.LENGTH_SHORT).show(); 85 | break; 86 | case R.id.button32: 87 | Toast.makeText(getActivity(), "Two", Toast.LENGTH_SHORT).show(); 88 | break; 89 | case R.id.button33: 90 | Toast.makeText(getActivity(), "Three", Toast.LENGTH_SHORT).show(); 91 | break; 92 | default: 93 | // Nothing to do 94 | } 95 | } 96 | 97 | @Override 98 | public void onClick(View v) { 99 | switch (v.getId()) { 100 | case R.id.add_segmented: 101 | addButton(segmented5); 102 | break; 103 | case R.id.remove_segmented: 104 | removeButton(segmented5); 105 | break; 106 | default: 107 | // Nothing to do 108 | } 109 | } 110 | 111 | private void addButton(SegmentedGroup group) { 112 | RadioButton radioButton = (RadioButton) getActivity().getLayoutInflater().inflate(R.layout.radio_button_item, null); 113 | radioButton.setText("Button " + (group.getChildCount() + 1)); 114 | group.addView(radioButton); 115 | group.updateBackground(); 116 | } 117 | 118 | private void removeButton(SegmentedGroup group) { 119 | if (group.getChildCount() < 1) return; 120 | group.removeViewAt(group.getChildCount() - 1); 121 | group.updateBackground(); 122 | 123 | //Update margin for last item 124 | if (group.getChildCount() < 1) return; 125 | RadioGroup.LayoutParams layoutParams = new RadioGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 126 | layoutParams.setMargins(0, 0, 0, 0); 127 | group.getChildAt(group.getChildCount() - 1).setLayoutParams(layoutParams); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /demo/src/main/java/info/hoang8f/mymo/segmented/demo/SampleApplication.java: -------------------------------------------------------------------------------- 1 | package info.hoang8f.mymo.segmented.demo; 2 | 3 | import android.app.Application; 4 | 5 | import info.hoang8f.android.segmented.utils.TypefaceProvider; 6 | 7 | public class SampleApplication extends Application { 8 | @Override 9 | public void onCreate() { 10 | super.onCreate(); 11 | TypefaceProvider.registerDefaultIconSets(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kaopiz/android-segmented-control/519e553c84a351929d4ef2fdf31854e3a36735b9/demo/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kaopiz/android-segmented-control/519e553c84a351929d4ef2fdf31854e3a36735b9/demo/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kaopiz/android-segmented-control/519e553c84a351929d4ef2fdf31854e3a36735b9/demo/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kaopiz/android-segmented-control/519e553c84a351929d4ef2fdf31854e3a36735b9/demo/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/layout/activity_sample.xml: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/fragment_sample.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | 20 | 21 | 32 | 33 | 40 | 41 | 48 | 49 | 50 | 51 | 52 | 57 | 58 | 67 | 68 | 74 | 75 | 81 | 82 | 88 | 89 | 90 | 91 | 92 | 98 | 99 | 108 | 109 | 116 | 117 | 124 | 125 | 132 | 133 | 134 | 135 | 136 | 137 | 141 | 142 | 149 | 150 | 158 | 159 | 165 | 166 | 172 | 173 | 174 | 175 | 176 | 183 | 184 | 192 | 193 | 198 | 199 | 204 | 205 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 221 | 222 | 226 | 227 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 246 | 247 |