Repository: saeedsh92/Banner-Slider Branch: master Commit: 291e18d5a629 Files: 59 Total size: 86.1 KB Directory structure: gitextract_3qbqixxs/ ├── .gitignore ├── README.md ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── ss/ │ │ └── com/ │ │ └── bannerslidersample/ │ │ ├── MainActivity.java │ │ ├── MainSliderAdapter.java │ │ └── PicassoImageLoadingService.java │ └── res/ │ ├── drawable-xxhdpi/ │ │ ├── selected_slide_indicator.xml │ │ └── unselected_slide_indicator.xml │ ├── layout/ │ │ ├── activity_main.xml │ │ └── layout_empty_view.xml │ ├── values/ │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── values-w820dp/ │ └── dimens.xml ├── bannerslider/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── ss/ │ │ └── com/ │ │ └── bannerslider/ │ │ ├── Config.java │ │ ├── ImageLoadingService.java │ │ ├── SlideIndicatorsGroup.java │ │ ├── SlideType.java │ │ ├── Slider.java │ │ ├── SsSnapHelper.java │ │ ├── adapters/ │ │ │ ├── PositionController.java │ │ │ ├── SliderAdapter.java │ │ │ └── SliderRecyclerViewAdapter.java │ │ ├── event/ │ │ │ ├── OnSlideChangeListener.java │ │ │ └── OnSlideClickListener.java │ │ ├── indicators/ │ │ │ ├── CircleIndicator.java │ │ │ ├── DashIndicator.java │ │ │ ├── IndicatorShape.java │ │ │ ├── RoundSquareIndicator.java │ │ │ └── SquareIndicator.java │ │ └── viewholder/ │ │ └── ImageSlideViewHolder.java │ └── res/ │ ├── drawable/ │ │ ├── indicator_circle_selected.xml │ │ ├── indicator_circle_unselected.xml │ │ ├── indicator_dash_selected.xml │ │ ├── indicator_dash_unselected.xml │ │ ├── indicator_round_square_selected.xml │ │ ├── indicator_round_square_unselected.xml │ │ ├── indicator_square_selected.xml │ │ └── indicator_square_unselected.xml │ ├── layout/ │ │ └── item_slide_image.xml │ └── values/ │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ └── strings.xml ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.iml .gradle /local.properties .DS_Store /build /captures .externalNativeBuild /.idea ================================================ FILE: README.md ================================================ # Deprecated ### I created this project in 2016. many things have changed and there are many other new great alternatives for creating sliders in android. so I decided to deprecate banner-slider. # Banner-Slider Banner slider is an easy to use library for making beautiful sliders in your android app. ## How to download ### Gradle add this line to your module build.gradle dependecies block: compile 'com.ss.bannerslider:bannerslider:2.0.0' ### Maven com.ss.bannerslider bannerslider 2.0.0 pom ## How use this library ### XML ```xml ``` ### Java ### Step 1: extend SliderAdapter in first step you must create an adapter to adapt your data model with slides. example implemented adapter with 3 slides: ```java public class MainSliderAdapter extends SliderAdapter { @Override public int getItemCount() { return 3; } @Override public void onBindImageSlide(int position, ImageSlideViewHolder viewHolder) { switch (position) { case 0: viewHolder.bindImageSlide("https://assets.materialup.com/uploads/dcc07ea4-845a-463b-b5f0-4696574da5ed/preview.jpg"); break; case 1: viewHolder.bindImageSlide("https://assets.materialup.com/uploads/20ded50d-cc85-4e72-9ce3-452671cf7a6d/preview.jpg"); break; case 2: viewHolder.bindImageSlide("https://assets.materialup.com/uploads/76d63bbc-54a1-450a-a462-d90056be881b/preview.png"); break; } } } ``` ### Step 2: specify your image loading service you must specify image loading service for loading images(for better flexibility and prevent adding unnecessary libraries). for example if you work with picasso for loading images in your project, you must implement ImageLoadingService interface like below: ```java public class PicassoImageLoadingService implements ImageLoadingService { public Context context; public PicassoImageLoadingService(Context context) { this.context = context; } @Override public void loadImage(String url, ImageView imageView) { Picasso.with(context).load(url).into(imageView); } @Override public void loadImage(int resource, ImageView imageView) { Picasso.with(context).load(resource).into(imageView); } @Override public void loadImage(String url, int placeHolder, int errorDrawable, ImageView imageView) { Picasso.with(context).load(url).placeholder(placeHolder).error(errorDrawable).into(imageView); } } ``` ### Step 3: initialize slider in your Application class ```java Slider.init(YOUR IMAGE LOADING SERVICE); ``` ### Step 4: set your adapter on slider ```java slider = findViewById(R.id.banner_slider1); slider.setAdapter(new MainSliderAdapter()); ``` ## You want more customization? #### Changing slides automatically in specifed periods interval attribute get miliseconds. ```xml app:slider_interval="5000" ``` #### Loop slides ```xml app:slider_loopSlides="true" ``` #### Choose default banner to show up first ```java slider.setSelectedSlide(2); ``` you must pass banner position to it: ```xml app:slider_defaultBanner="1" ``` #### Enable/disable indicators animations in default, animations are enabled ```xml app:slider_animateIndicators="true" ``` #### Use custom Indicators if you also set default indicators, then this attributes will ignored ```xml app:slider_selectedSlideIndicator="@drawable/selected_slide_indicator" app:slider_unselectedSlideIndicator="@drawable/unselected_slide_indicator" ``` #### How set empty view, when banners not received from server yet? ```xml app:slider_emptyView="@layout/layout_empty_view" ``` #### Change indicator sizes ```xml app:slider_indicatorSize="12dp" ``` #### Set OnBannerClickListener ```java slider.setOnSlideClickListener(new OnSlideClickListener() { @Override public void onSlideClick(int position) { //Do what you want } }); }); ``` ## Licence Copyright 2016 Saeed Shahini 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 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ## Author Saeed shahini email: saeedshahiniit@gmail.com github: https://github.com/saeedsh92 ================================================ FILE: app/.gitignore ================================================ /build ================================================ FILE: app/build.gradle ================================================ apply plugin: 'com.android.application' android { compileSdkVersion 26 defaultConfig { applicationId "ss.com.bannerslidersample" minSdkVersion 14 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation 'com.android.support:appcompat-v7:26.1.0' implementation project(':bannerslider') implementation 'com.android.support:design:26.1.0' implementation 'com.android.support:support-vector-drawable:26.1.0' implementation 'com.squareup.picasso:picasso:2.5.2' implementation 'com.android.support:cardview-v7:26.0.0-alpha1' implementation 'com.android.support:customtabs:26.0.0-alpha1' } ================================================ FILE: app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /home/saeed/android-sdk/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: app/src/main/java/ss/com/bannerslidersample/MainActivity.java ================================================ package ss.com.bannerslidersample; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.customtabs.CustomTabsIntent; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.SwitchCompat; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.SeekBar; import android.widget.Spinner; import ss.com.bannerslider.Slider; import ss.com.bannerslider.indicators.IndicatorShape; public class MainActivity extends AppCompatActivity { private Slider slider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Slider.init(new PicassoImageLoadingService(this)); setupViews(); } private void setupViews() { setupToolbar(); setupPageIndicatorChooser(); setupSettingsUi(); slider = findViewById(R.id.banner_slider1); //delay for testing empty view functionality slider.postDelayed(new Runnable() { @Override public void run() { slider.setAdapter(new MainSliderAdapter()); slider.setSelectedSlide(0); } }, 1500); } private void setupSettingsUi() { final SeekBar intervalSeekBar = findViewById(R.id.seekbar_interval); intervalSeekBar.setMax(10000); intervalSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { if (b) { slider.setInterval(i); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); SeekBar indicatorSizeSeekBar = findViewById(R.id.seekbar_indicator_size); indicatorSizeSeekBar.setMax(getResources().getDimensionPixelSize(R.dimen.max_slider_indicator_size)); indicatorSizeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { if (b) { slider.setIndicatorSize(i); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); SwitchCompat loopSlidesSwitch = findViewById(R.id.checkbox_loop_slides); loopSlidesSwitch.setChecked(true); SwitchCompat mustAnimateIndicators = findViewById(R.id.checkbox_animate_indicators); mustAnimateIndicators.setChecked(true); loopSlidesSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { slider.setLoopSlides(b); } }); mustAnimateIndicators.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { slider.setAnimateIndicators(b); } }); SwitchCompat hideIndicatorsSwitch = findViewById(R.id.checkbox_hide_indicators); hideIndicatorsSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { if (b) { slider.hideIndicators(); } else { slider.showIndicators(); } } }); } private void setupToolbar() { Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); ImageView githubSourceImageView = findViewById(R.id.image_github); githubSourceImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Uri uri = Uri.parse("https://github.com/saeedsh92/Banner-Slider"); if (Build.VERSION.SDK_INT > 15) { CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder(); intentBuilder.setToolbarColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimary)); intentBuilder.setSecondaryToolbarColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimaryDark)); intentBuilder.setStartAnimations(MainActivity.this, android.R.anim.fade_in, android.R.anim.fade_out); intentBuilder.setExitAnimations(MainActivity.this, android.R.anim.fade_in, android.R.anim.fade_out); CustomTabsIntent customTabsIntent = intentBuilder.build(); customTabsIntent.launchUrl(MainActivity.this, uri); } else { startActivity(Intent.createChooser(new Intent(Intent.ACTION_VIEW, uri), "Choose Browser...")); } } }); } private void setupPageIndicatorChooser() { String[] pageIndicatorsLabels = getResources().getStringArray(R.array.page_indicators); ArrayAdapter arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, pageIndicatorsLabels ); Spinner spinner = findViewById(R.id.spinner_page_indicator); spinner.setAdapter(arrayAdapter); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView adapterView, View view, int i, long l) { switch (i) { case 0: slider.setIndicatorStyle(IndicatorShape.CIRCLE); break; case 1: slider.setIndicatorStyle(IndicatorShape.DASH); break; case 2: slider.setIndicatorStyle(IndicatorShape.ROUND_SQUARE); break; case 3: slider.setIndicatorStyle(IndicatorShape.SQUARE); break; case 4: slider.setSelectedSlideIndicator(ContextCompat.getDrawable(MainActivity.this, R.drawable.selected_slide_indicator)); slider.setUnSelectedSlideIndicator(ContextCompat.getDrawable(MainActivity.this, R.drawable.unselected_slide_indicator)); break; } } @Override public void onNothingSelected(AdapterView adapterView) { } }); } } ================================================ FILE: app/src/main/java/ss/com/bannerslidersample/MainSliderAdapter.java ================================================ package ss.com.bannerslidersample; import ss.com.bannerslider.SlideType; import ss.com.bannerslider.adapters.SliderAdapter; import ss.com.bannerslider.viewholder.ImageSlideViewHolder; /** * @author S.Shahini * @since 2/12/18 */ public class MainSliderAdapter extends SliderAdapter { @Override public int getItemCount() { return 3; } @Override public void onBindImageSlide(int position, ImageSlideViewHolder viewHolder) { switch (position) { case 0: viewHolder.bindImageSlide("https://assets.materialup.com/uploads/dcc07ea4-845a-463b-b5f0-4696574da5ed/preview.jpg"); break; case 1: viewHolder.bindImageSlide("https://assets.materialup.com/uploads/20ded50d-cc85-4e72-9ce3-452671cf7a6d/preview.jpg"); break; case 2: viewHolder.bindImageSlide("https://assets.materialup.com/uploads/76d63bbc-54a1-450a-a462-d90056be881b/preview.png"); break; } } } ================================================ FILE: app/src/main/java/ss/com/bannerslidersample/PicassoImageLoadingService.java ================================================ package ss.com.bannerslidersample; import android.content.Context; import android.widget.ImageView; import com.squareup.picasso.Picasso; import ss.com.bannerslider.ImageLoadingService; /** * @author S.Shahini * @since 4/7/18 */ public class PicassoImageLoadingService implements ImageLoadingService { public Context context; public PicassoImageLoadingService(Context context) { this.context = context; } @Override public void loadImage(String url, ImageView imageView) { Picasso.with(context).load(url).into(imageView); } @Override public void loadImage(int resource, ImageView imageView) { Picasso.with(context).load(resource).into(imageView); } @Override public void loadImage(String url, int placeHolder, int errorDrawable, ImageView imageView) { Picasso.with(context).load(url).placeholder(placeHolder).error(errorDrawable).into(imageView); } } ================================================ FILE: app/src/main/res/drawable-xxhdpi/selected_slide_indicator.xml ================================================ ================================================ FILE: app/src/main/res/drawable-xxhdpi/unselected_slide_indicator.xml ================================================ ================================================ FILE: app/src/main/res/layout/activity_main.xml ================================================ ================================================ FILE: app/src/main/res/layout/layout_empty_view.xml ================================================ ================================================ FILE: app/src/main/res/values/colors.xml ================================================ #fff #aaaaaa #2facb2 #eeee #717171 ================================================ FILE: app/src/main/res/values/dimens.xml ================================================ 16dp 16dp 8dp 16dp 20dp ================================================ FILE: app/src/main/res/values/strings.xml ================================================ BannerSliderSample This Is Empty View Interval: Indicator size: Animate indicators: Hide Indicators Loop slides: Circle Dash Round Square Square Custom ================================================ FILE: app/src/main/res/values/styles.xml ================================================ ================================================ FILE: app/src/main/res/values-w820dp/dimens.xml ================================================ 64dp ================================================ FILE: bannerslider/.gitignore ================================================ /build ================================================ FILE: bannerslider/build.gradle ================================================ apply plugin: 'com.android.library' android { compileSdkVersion 26 defaultConfig { minSdkVersion 14 targetSdkVersion 26 versionCode 10 versionName "2.0.0" group = 'com.ss.bannerslider' version = '2.0.0' } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation 'com.android.support:recyclerview-v7:26.1.0' } ================================================ FILE: bannerslider/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /home/saeed/android-sdk/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: bannerslider/src/main/AndroidManifest.xml ================================================ ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/Config.java ================================================ package ss.com.bannerslider; import android.content.Context; import android.graphics.drawable.Drawable; import android.support.v4.content.ContextCompat; /** * @author S.Shahini * @since 3/5/18 */ public class Config { public static final int NOT_SELECTED = -1; protected boolean hideIndicators = false; protected boolean loopSlides = true; protected int indicatorSize = NOT_SELECTED; protected Drawable selectedSlideIndicator; protected Drawable unselectedSlideIndicator; protected boolean animateIndicators = true; protected int slideChangeInterval = 0; protected int emptyView = NOT_SELECTED; private Config() { } public static class Builder { private Config config = new Config(); private Context context; public Builder(Context context) { this.context = context.getApplicationContext(); } public Builder hideIndicators(boolean hideIndicators) { config.hideIndicators = hideIndicators; return this; } public Builder loopSlides(boolean loopSlides) { config.loopSlides = loopSlides; return this; } public Builder indicatorSize(int indicatorSize) { config.indicatorSize = indicatorSize; return this; } public Builder selectedSlideIndicator(Drawable selectedSlideIndicator) { config.selectedSlideIndicator = selectedSlideIndicator; return this; } public Builder unselectedSlideIndicator(Drawable unselectedSlideIndicator) { config.unselectedSlideIndicator = unselectedSlideIndicator; return this; } public Builder animateIndicators(boolean animateIndicators) { config.animateIndicators = animateIndicators; return this; } public Builder slideChangeInterval(int slideChangeInterval) { config.slideChangeInterval = slideChangeInterval; return this; } public Builder emptyView(int emptyView) { config.emptyView = emptyView; return this; } public Config build() { if (config.selectedSlideIndicator == null) { config.selectedSlideIndicator = ContextCompat.getDrawable(context, R.drawable.indicator_circle_selected); } if (config.unselectedSlideIndicator == null) { config.unselectedSlideIndicator = ContextCompat.getDrawable(context, R.drawable.indicator_circle_unselected); } if (config.indicatorSize == NOT_SELECTED) { config.indicatorSize = context.getResources().getDimensionPixelSize(R.dimen.default_indicator_size); } return config; } } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/ImageLoadingService.java ================================================ package ss.com.bannerslider; import android.support.annotation.DrawableRes; import android.widget.ImageView; /** * @author S.Shahini * @since 4/4/18 */ public interface ImageLoadingService { void loadImage(String url, ImageView imageView); void loadImage(@DrawableRes int resource, ImageView imageView); void loadImage(String url, @DrawableRes int placeHolder, @DrawableRes int errorDrawable, ImageView imageView); } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/SlideIndicatorsGroup.java ================================================ package ss.com.bannerslider; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.Log; import android.view.Gravity; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.LinearLayout; import java.util.ArrayList; import java.util.List; import ss.com.bannerslider.event.OnSlideChangeListener; import ss.com.bannerslider.indicators.CircleIndicator; import ss.com.bannerslider.indicators.DashIndicator; import ss.com.bannerslider.indicators.IndicatorShape; import ss.com.bannerslider.indicators.RoundSquareIndicator; import ss.com.bannerslider.indicators.SquareIndicator; /** * @author S.Shahini * @since 11/26/16 */ class SlideIndicatorsGroup extends LinearLayout implements OnSlideChangeListener { private static final String TAG = "SlideIndicatorsGroup"; private final Context context; private int slidesCount; private Drawable selectedSlideIndicator; private Drawable unselectedSlideIndicator; private int defaultIndicator; private int indicatorSize; private boolean mustAnimateIndicators = true; private List indicatorShapes = new ArrayList<>(); public SlideIndicatorsGroup(Context context, Drawable selectedSlideIndicator, Drawable unselectedSlideIndicator, int defaultIndicator, int indicatorSize, boolean mustAnimateIndicators) { super(context); this.context = context; this.selectedSlideIndicator = selectedSlideIndicator; this.unselectedSlideIndicator = unselectedSlideIndicator; this.defaultIndicator = defaultIndicator; this.indicatorSize = indicatorSize; this.mustAnimateIndicators = mustAnimateIndicators; setup(); } public void setSlides(int slidesCount) { removeAllViews(); indicatorShapes.clear(); this.slidesCount = 0; for (int i = 0; i < slidesCount; i++) { onSlideAdd(); } this.slidesCount = slidesCount; } public void onSlideAdd() { this.slidesCount += 1; addIndicator(); } private void addIndicator() { IndicatorShape indicatorShape; if (selectedSlideIndicator != null && unselectedSlideIndicator != null) { indicatorShape = new IndicatorShape(context, indicatorSize, mustAnimateIndicators) { @Override public void onCheckedChange(boolean isChecked) { super.onCheckedChange(isChecked); if (isChecked) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(selectedSlideIndicator); } else { setBackgroundDrawable(selectedSlideIndicator); } } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(unselectedSlideIndicator); } else { setBackgroundDrawable(unselectedSlideIndicator); } } } }; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { indicatorShape.setBackground(unselectedSlideIndicator); } else { indicatorShape.setBackgroundDrawable(unselectedSlideIndicator); } indicatorShapes.add(indicatorShape); addView(indicatorShape); } else { switch (defaultIndicator) { case IndicatorShape.SQUARE: indicatorShape = new SquareIndicator(context, indicatorSize, mustAnimateIndicators); indicatorShapes.add(indicatorShape); addView(indicatorShape); break; case IndicatorShape.ROUND_SQUARE: indicatorShape = new RoundSquareIndicator(context, indicatorSize, mustAnimateIndicators); indicatorShapes.add(indicatorShape); addView(indicatorShape); break; case IndicatorShape.DASH: indicatorShape = new DashIndicator(context, indicatorSize, mustAnimateIndicators); indicatorShapes.add(indicatorShape); addView(indicatorShape); break; case IndicatorShape.CIRCLE: indicatorShape = new CircleIndicator(context, indicatorSize, mustAnimateIndicators); indicatorShapes.add(indicatorShape); addView(indicatorShape); break; default: break; } } } public void setup() { setOrientation(LinearLayout.HORIZONTAL); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; int margin = getResources().getDimensionPixelSize(R.dimen.default_indicator_margins) * 2; layoutParams.setMargins(0, 0, 0, margin); setLayoutParams(layoutParams); } @Override public void onSlideChange(int selectedSlidePosition) { Log.i(TAG, "onSlideChange: "+selectedSlidePosition); for (int i = 0; i < indicatorShapes.size(); i++) { if (i == selectedSlidePosition) { indicatorShapes.get(i).onCheckedChange(true); } else { indicatorShapes.get(i).onCheckedChange(false); } } } public void setMustAnimateIndicators(boolean shouldAnimate) { this.mustAnimateIndicators = shouldAnimate; for (IndicatorShape indicatorShape : indicatorShapes) { indicatorShape.setMustAnimateChange(shouldAnimate); } } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/SlideType.java ================================================ package ss.com.bannerslider; public enum SlideType { //Custom,Video And Gif Slides will add in future IMAGE(0); private final int value; SlideType(int value) { this.value = value; } public int getValue() { return this.value; } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/Slider.java ================================================ package ss.com.bannerslider; import android.app.Activity; import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import java.util.Timer; import java.util.TimerTask; import ss.com.bannerslider.adapters.PositionController; import ss.com.bannerslider.adapters.SliderAdapter; import ss.com.bannerslider.adapters.SliderRecyclerViewAdapter; import ss.com.bannerslider.event.OnSlideChangeListener; import ss.com.bannerslider.event.OnSlideClickListener; import ss.com.bannerslider.indicators.IndicatorShape; /** * @author S.Shahini * @since 12/16/17 */ public class Slider extends FrameLayout { private static final String TAG = "Slider"; public OnSlideChangeListener onSlideChangeListener; public OnSlideClickListener onSlideClickListener; public RecyclerView recyclerView; public SliderRecyclerViewAdapter adapter; public SlideIndicatorsGroup slideIndicatorsGroup; public int pendingPosition = RecyclerView.NO_POSITION; public SliderAdapter sliderAdapter; public Config config; public int selectedSlidePosition = 0; public Timer timer; public PositionController positionController; public static ImageLoadingService imageLoadingService; private View emptyView; public Slider(@NonNull Context context) { super(context); setupViews(null); } public Slider(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); setupViews(attrs); } public Slider(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setupViews(attrs); } private void setupViews(AttributeSet attributeSet) { if (attributeSet != null) { TypedArray typedArray = getContext().obtainStyledAttributes(attributeSet, R.styleable.Slider); try { config = new Config.Builder(getContext()) .animateIndicators(typedArray.getBoolean(R.styleable.Slider_slider_animateIndicators, true)) .emptyView(typedArray.getResourceId(R.styleable.Slider_slider_emptyView, Config.NOT_SELECTED)) .indicatorSize(typedArray.getDimensionPixelSize(R.styleable.Slider_slider_indicatorSize, 0)) .loopSlides(typedArray.getBoolean(R.styleable.Slider_slider_loopSlides, false)) .slideChangeInterval(typedArray.getInteger(R.styleable.Slider_slider_interval, 0)) .selectedSlideIndicator(typedArray.getDrawable(R.styleable.Slider_slider_selectedSlideIndicator)) .unselectedSlideIndicator(typedArray.getDrawable(R.styleable.Slider_slider_unselectedSlideIndicator)) .hideIndicators(typedArray.getBoolean(R.styleable.Slider_slider_hideIndicators, false)) .build(); } catch (Exception e) { Log.e("Slider", "setupViews: ".toString()); } finally { typedArray.recycle(); } } else { config = new Config.Builder(getContext()).build(); } setupRv(); setupSlideIndicator(); } private void setupRv() { recyclerView = new RecyclerView(getContext()); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (!config.loopSlides) return; if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (selectedSlidePosition == 0) { recyclerView.scrollToPosition(adapter.getItemCount() - 2); onImageSlideChange(adapter.getItemCount() - 2); } else if (selectedSlidePosition == adapter.getItemCount() - 1) { recyclerView.scrollToPosition(1); onImageSlideChange(1); } } } }); if (config.emptyView != Config.NOT_SELECTED) { emptyView = LayoutInflater.from(getContext()).inflate(config.emptyView, this, false); addView(emptyView); } } private void setupSlideIndicator() { if (!config.hideIndicators) { slideIndicatorsGroup = new SlideIndicatorsGroup(getContext(), config.selectedSlideIndicator, config.unselectedSlideIndicator, 0, config.indicatorSize, config.animateIndicators); } } public void onImageSlideChange(int position) { Log.d(TAG, "onImageSlideChange() called with: position = [" + position + "]"); selectedSlidePosition = position; int userSlidePosition = positionController.getUserSlidePosition(position); if (slideIndicatorsGroup != null) slideIndicatorsGroup.onSlideChange(userSlidePosition); if (onSlideChangeListener != null) { onSlideChangeListener.onSlideChange(userSlidePosition); } } public void setSelectedSlide(int position, boolean animate) { if (recyclerView != null && recyclerView.getAdapter() != null) { if (animate) { recyclerView.smoothScrollToPosition(position); } else { recyclerView.scrollToPosition(position); } onImageSlideChange(position); } else { pendingPosition = position; } } public void setSelectedSlide(int position) { setSelectedSlide(positionController.getRealSlidePosition(position), true); } private void onAdapterAttached() { if (pendingPosition != RecyclerView.NO_POSITION) { recyclerView.smoothScrollToPosition(pendingPosition); onImageSlideChange(pendingPosition); pendingPosition = RecyclerView.NO_POSITION; } } public void setSlideChangeListener(OnSlideChangeListener onSlideChangeListener) { this.onSlideChangeListener = onSlideChangeListener; } public void setOnSlideClickListener(OnSlideClickListener onSlideClickListener) { this.onSlideClickListener = onSlideClickListener; if (adapter != null) adapter.setOnSlideClickListener(onSlideClickListener); } public SliderAdapter getAdapter() { return this.sliderAdapter; } public void setAdapter(SliderAdapter sliderAdapter) { if (sliderAdapter != null && recyclerView != null) { this.sliderAdapter = sliderAdapter; if (indexOfChild(recyclerView) == -1) { if (getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) { recyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } else { recyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); } addView(recyclerView); } recyclerView.setNestedScrollingEnabled(false); final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false); recyclerView.setLayoutManager(linearLayoutManager); positionController = new PositionController(sliderAdapter, config.loopSlides); adapter = new SliderRecyclerViewAdapter(sliderAdapter, sliderAdapter.getItemCount() > 1 && config.loopSlides, recyclerView.getLayoutParams(), new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { stopTimer(); } else if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) { startTimer(); } return false; } }, positionController); recyclerView.setAdapter(adapter); positionController.setRecyclerViewAdapter(adapter); //Show default selected slide selectedSlidePosition = config.loopSlides ? 1 : 0; recyclerView.scrollToPosition(selectedSlidePosition); onImageSlideChange(selectedSlidePosition); pendingPosition = RecyclerView.NO_POSITION; onAdapterAttached(); SsSnapHelper snapHelper = new SsSnapHelper(new SsSnapHelper.OnSelectedItemChange() { @Override public void onSelectedItemChange(int position) { onImageSlideChange(position); } }); recyclerView.setOnFlingListener(null); snapHelper.attachToRecyclerView(recyclerView); if (slideIndicatorsGroup != null && sliderAdapter.getItemCount() > 1) { if (indexOfChild(slideIndicatorsGroup) == -1) { addView(slideIndicatorsGroup); } slideIndicatorsGroup.setSlides(sliderAdapter.getItemCount()); slideIndicatorsGroup.onSlideChange(0); } if (emptyView != null) { emptyView.setVisibility(GONE); } } } public Config getConfig() { return this.config; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); startTimer(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); stopTimer(); } private void startTimer() { if (config.slideChangeInterval > 0) { stopTimer(); timer = new Timer(); timer.schedule(new SliderTimerTask(), config.slideChangeInterval, config.slideChangeInterval); } } private void stopTimer() { if (timer != null) { timer.cancel(); timer.purge(); } } public static void init(ImageLoadingService imageLoadingService) { Slider.imageLoadingService = imageLoadingService; } public static ImageLoadingService getImageLoadingService() { if (imageLoadingService == null) { throw new IllegalStateException("ImageLoadingService is null, you should call init method first"); } return imageLoadingService; } private class SliderTimerTask extends TimerTask { @Override public void run() { if (getContext() instanceof Activity) { ((Activity) getContext()).runOnUiThread(new Runnable() { @Override public void run() { int nextSlidePosition = positionController.getNextSlide(selectedSlidePosition); recyclerView.smoothScrollToPosition(nextSlidePosition); onImageSlideChange(nextSlidePosition); } }); } } } public void setInterval(int interval) { config.slideChangeInterval = interval; stopTimer(); startTimer(); } public void setLoopSlides(boolean loopSlides) { config.loopSlides = loopSlides; adapter.setLoop(loopSlides); positionController.setLoop(loopSlides); adapter.notifyDataSetChanged(); recyclerView.scrollToPosition(loopSlides ? 1 : 0); onImageSlideChange(loopSlides ? 1 : 0); } public void setAnimateIndicators(boolean shouldAnimate) { config.animateIndicators = shouldAnimate; if (slideIndicatorsGroup != null) slideIndicatorsGroup.setMustAnimateIndicators(shouldAnimate); } public void hideIndicators() { config.hideIndicators = true; if (slideIndicatorsGroup != null) slideIndicatorsGroup.setVisibility(GONE); } public void showIndicators() { config.hideIndicators = false; if (slideIndicatorsGroup != null) slideIndicatorsGroup.setVisibility(VISIBLE); } public void setIndicatorSize(int indicatorSize) { config.indicatorSize = indicatorSize; refreshIndicators(); } public void setSelectedSlideIndicator(Drawable selectedSlideIndicator) { config.selectedSlideIndicator = selectedSlideIndicator; refreshIndicators(); } public void setUnSelectedSlideIndicator(Drawable unSelectedSlideIndicator) { config.unselectedSlideIndicator = unSelectedSlideIndicator; refreshIndicators(); } private void refreshIndicators() { if (!config.hideIndicators && sliderAdapter != null) { if (slideIndicatorsGroup != null) { removeView(slideIndicatorsGroup); } slideIndicatorsGroup = new SlideIndicatorsGroup(getContext(), config.selectedSlideIndicator, config.unselectedSlideIndicator, 0, config.indicatorSize, config.animateIndicators); addView(slideIndicatorsGroup); for (int i = 0; i < sliderAdapter.getItemCount(); i++) { slideIndicatorsGroup.onSlideAdd(); } } } public void setIndicatorStyle(int indicatorStyle) { switch (indicatorStyle) { case IndicatorShape.CIRCLE: config.selectedSlideIndicator = ContextCompat.getDrawable(getContext(), R.drawable.indicator_circle_selected); config.unselectedSlideIndicator = ContextCompat.getDrawable(getContext(), R.drawable.indicator_circle_unselected); break; case IndicatorShape.SQUARE: config.selectedSlideIndicator = ContextCompat.getDrawable(getContext(), R.drawable.indicator_square_selected); config.unselectedSlideIndicator = ContextCompat.getDrawable(getContext(), R.drawable.indicator_square_unselected); break; case IndicatorShape.DASH: config.selectedSlideIndicator = ContextCompat.getDrawable(getContext(), R.drawable.indicator_dash_selected); config.unselectedSlideIndicator = ContextCompat.getDrawable(getContext(), R.drawable.indicator_dash_unselected); break; case IndicatorShape.ROUND_SQUARE: config.selectedSlideIndicator = ContextCompat.getDrawable(getContext(), R.drawable.indicator_round_square_selected); config.unselectedSlideIndicator = ContextCompat.getDrawable(getContext(), R.drawable.indicator_round_square_unselected); break; } refreshIndicators(); } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/SsSnapHelper.java ================================================ package ss.com.bannerslider; import android.support.v7.widget.PagerSnapHelper; import android.support.v7.widget.RecyclerView; /** * @author S.Shahini * @since 2/17/18 */ class SsSnapHelper extends PagerSnapHelper { private OnSelectedItemChange onSelectedItemChange; private int lastPosition; public SsSnapHelper(OnSelectedItemChange onSelectedItemChange) { this.onSelectedItemChange = onSelectedItemChange; } @Override public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) { int position = super.findTargetSnapPosition(layoutManager, velocityX, velocityY); if (position != RecyclerView.NO_POSITION && lastPosition != position && position < layoutManager.getItemCount()) { onSelectedItemChange.onSelectedItemChange(position); lastPosition = position; } return position; } public interface OnSelectedItemChange { void onSelectedItemChange(int position); } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/adapters/PositionController.java ================================================ package ss.com.bannerslider.adapters; import android.util.Log; /** * @author S.Shahini * @since 4/7/18 */ public class PositionController { private static final String TAG = "PositionController"; private SliderRecyclerViewAdapter recyclerViewAdapter; private SliderAdapter sliderAdapter; private boolean loop; public PositionController(SliderAdapter sliderAdapter, boolean loop) { this.sliderAdapter = sliderAdapter; this.loop = loop; } public int getUserSlidePosition(int position) { if (loop) { if (position == 0) { return recyclerViewAdapter.getItemCount() - 3; } else if (position == recyclerViewAdapter.getItemCount() - 1) { return 0; } else { return position - 1; } } else { return position; } } public int getRealSlidePosition(int position) { if (!loop) { return position; } else { if (position >= 0 && position < sliderAdapter.getItemCount()) { return position + 1; } else { Log.e(TAG, "setSelectedSlide: Invalid Item Position"); return 1; } } } public int getLastUserSlidePosition() { return sliderAdapter.getItemCount() - 1; } public int getFirstUserSlidePosition() { return 0; } public void setRecyclerViewAdapter(SliderRecyclerViewAdapter recyclerViewAdapter) { this.recyclerViewAdapter = recyclerViewAdapter; } public int getNextSlide(int currentPosition) { if (currentPosition < recyclerViewAdapter.getItemCount() - 1) { return currentPosition + 1; } else { return loop ? 1 : 0; } } public void setLoop(boolean loop) { this.loop = loop; } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/adapters/SliderAdapter.java ================================================ package ss.com.bannerslider.adapters; import ss.com.bannerslider.SlideType; import ss.com.bannerslider.viewholder.ImageSlideViewHolder; /** * @author S.Shahini * @since 3/4/18 */ public abstract class SliderAdapter { public abstract int getItemCount(); public final SlideType getSlideType(int position) { return SlideType.IMAGE; } public abstract void onBindImageSlide(int position, ImageSlideViewHolder imageSlideViewHolder); } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/adapters/SliderRecyclerViewAdapter.java ================================================ package ss.com.bannerslider.adapters; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import ss.com.bannerslider.SlideType; import ss.com.bannerslider.event.OnSlideClickListener; import ss.com.bannerslider.viewholder.ImageSlideViewHolder; /** * @author S.Shahini * @since 12/16/17 */ public class SliderRecyclerViewAdapter extends RecyclerView.Adapter { private ViewGroup.LayoutParams imageViewLayoutParams; private OnSlideClickListener onSlideClickListener; private SliderAdapter sliderAdapter; private boolean loop; private View.OnTouchListener itemOnTouchListener; private PositionController positionController; public SliderRecyclerViewAdapter(SliderAdapter iSliderAdapter, boolean loop, ViewGroup.LayoutParams imageViewLayoutParams, View.OnTouchListener itemOnTouchListener, PositionController positionController) { this.sliderAdapter = iSliderAdapter; this.imageViewLayoutParams = imageViewLayoutParams; this.loop = loop; this.itemOnTouchListener = itemOnTouchListener; this.positionController = positionController; } public void setOnSlideClickListener(OnSlideClickListener onSlideClickListener) { this.onSlideClickListener = onSlideClickListener; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == SlideType.IMAGE.getValue()) { ImageView imageView = new ImageView(parent.getContext()); imageView.setLayoutParams(imageViewLayoutParams); imageView.setAdjustViewBounds(true); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); return new ImageSlideViewHolder(imageView); } else { return null; } } @Override public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { if (!loop) { sliderAdapter.onBindImageSlide(position, (ImageSlideViewHolder) holder); } else { if (position == 0) { sliderAdapter.onBindImageSlide(positionController.getLastUserSlidePosition(), (ImageSlideViewHolder) holder); } else if (position == getItemCount() - 1) { sliderAdapter.onBindImageSlide(positionController.getFirstUserSlidePosition(), (ImageSlideViewHolder) holder); } else { sliderAdapter.onBindImageSlide(position - 1, (ImageSlideViewHolder) holder); } } holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (onSlideClickListener != null) onSlideClickListener.onSlideClick(positionController.getUserSlidePosition(holder.getAdapterPosition())); } }); holder.itemView.setOnTouchListener(itemOnTouchListener); } @Override public int getItemCount() { return sliderAdapter.getItemCount() + (loop ? 2 : 0); } public void setLoop(boolean loop) { this.loop = loop; } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/event/OnSlideChangeListener.java ================================================ package ss.com.bannerslider.event; /** * @author S.Shahini * @since 3/4/18 */ public interface OnSlideChangeListener { void onSlideChange(int position); } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/event/OnSlideClickListener.java ================================================ package ss.com.bannerslider.event; /** * @author S.Shahini * @since 3/4/18 */ public interface OnSlideClickListener { void onSlideClick(int position); } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/indicators/CircleIndicator.java ================================================ package ss.com.bannerslider.indicators; import android.content.Context; import android.os.Build; import android.support.v4.content.res.ResourcesCompat; import ss.com.bannerslider.R; /** * @author S.Shahini * @since 11/27/16 */ public class CircleIndicator extends IndicatorShape { public CircleIndicator(Context context, int indicatorSize, boolean mustAnimateChanges) { super(context, indicatorSize, mustAnimateChanges); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_circle_unselected, null)); } else { setBackgroundDrawable(getResources().getDrawable(R.drawable.indicator_circle_unselected)); } } @Override public void onCheckedChange(boolean isChecked) { super.onCheckedChange(isChecked); if (isChecked) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_circle_selected, null)); } else { setBackgroundDrawable(getResources().getDrawable(R.drawable.indicator_circle_selected)); } } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_circle_unselected, null)); } else { setBackgroundDrawable(getResources().getDrawable(R.drawable.indicator_circle_unselected)); } } } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/indicators/DashIndicator.java ================================================ package ss.com.bannerslider.indicators; import android.content.Context; import android.support.v4.content.res.ResourcesCompat; import android.widget.LinearLayout; import ss.com.bannerslider.R; /** * @author S.Shahini * @since 11/27/16 */ public class DashIndicator extends IndicatorShape { public DashIndicator(Context context, int indicatorSize, boolean mustAnimateChanges) { super(context, indicatorSize, mustAnimateChanges); setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_dash_unselected, null)); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams(); if (layoutParams != null) { layoutParams.width = getResources().getDimensionPixelSize(R.dimen.default_dash_indicator_width); setLayoutParams(layoutParams); } } @Override public void onCheckedChange(boolean isChecked) { super.onCheckedChange(isChecked); if (isChecked) { setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_dash_selected, null)); } else { setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_dash_unselected, null)); } } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/indicators/IndicatorShape.java ================================================ package ss.com.bannerslider.indicators; import android.content.Context; import android.view.Gravity; import android.view.animation.Animation; import android.view.animation.ScaleAnimation; import android.widget.ImageView; import android.widget.LinearLayout; import ss.com.bannerslider.R; /** * @author S.Shahini * @since 11/26/16 */ public abstract class IndicatorShape extends ImageView { private boolean isChecked = false; private int indicatorSize; private boolean mustAnimateChange; public static final int CIRCLE = 0; public static final int SQUARE = 1; public static final int ROUND_SQUARE = 2; public static final int DASH = 3; private static final int ANIMATION_DURATION = 150; public IndicatorShape(Context context, int indicatorSize, boolean mustAnimateChange) { super(context); this.indicatorSize = indicatorSize; this.mustAnimateChange = mustAnimateChange; setup(); } private void setup() { if (this.indicatorSize == 0) { indicatorSize = (int) getResources().getDimension(R.dimen.default_indicator_size); } LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(indicatorSize, indicatorSize); int margin = getResources().getDimensionPixelSize(R.dimen.default_indicator_margins); layoutParams.gravity = Gravity.CENTER_VERTICAL; layoutParams.setMargins(margin, 0, margin, 0); setLayoutParams(layoutParams); } public void onCheckedChange(boolean isChecked) { if (this.isChecked != isChecked) { if (mustAnimateChange) { if (isChecked) { scale(); } else { descale(); } }else { if (isChecked) { scale(0); } else { descale(0); } } this.isChecked = isChecked; } } private void scale() { scale(ANIMATION_DURATION); } private void scale(int duration) { ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 1.1f, 1f, 1.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); scaleAnimation.setDuration(duration); scaleAnimation.setFillAfter(true); startAnimation(scaleAnimation); } private void descale() { descale(ANIMATION_DURATION); } private void descale(int duration) { ScaleAnimation scaleAnimation = new ScaleAnimation(1.1f, 1f, 1.1f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); scaleAnimation.setDuration(duration); scaleAnimation.setFillAfter(true); startAnimation(scaleAnimation); } public void setMustAnimateChange(boolean mustAnimateChange){ this.mustAnimateChange=mustAnimateChange; } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/indicators/RoundSquareIndicator.java ================================================ package ss.com.bannerslider.indicators; import android.content.Context; import android.os.Build; import android.support.v4.content.res.ResourcesCompat; import ss.com.bannerslider.R; /** * @author S.Shahini * @since 11/27/16 */ public class RoundSquareIndicator extends IndicatorShape { public RoundSquareIndicator(Context context, int indicatorSize, boolean mustAnimateChanges) { super(context, indicatorSize, mustAnimateChanges); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(ResourcesCompat.getDrawable(getResources(),R.drawable.indicator_round_square_unselected, null)); } else { setBackgroundDrawable(getResources().getDrawable(R.drawable.indicator_round_square_unselected)); } } @Override public void onCheckedChange(boolean isChecked) { super.onCheckedChange(isChecked); if (isChecked) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_round_square_selected, null)); } else { setBackgroundDrawable(getResources().getDrawable(R.drawable.indicator_round_square_selected)); } } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_round_square_unselected, null)); } else { setBackgroundDrawable(getResources().getDrawable(R.drawable.indicator_round_square_unselected)); } } } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/indicators/SquareIndicator.java ================================================ package ss.com.bannerslider.indicators; import android.content.Context; import android.os.Build; import android.support.v4.content.res.ResourcesCompat; import ss.com.bannerslider.R; /** * @author S.Shahini * @since 11/27/16 */ public class SquareIndicator extends IndicatorShape { public SquareIndicator(Context context, int indicatorSize, boolean mustAnimateChanges) { super(context, indicatorSize, mustAnimateChanges); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_square_unselected, null)); } else { setBackgroundDrawable(getResources().getDrawable(R.drawable.indicator_square_unselected)); } } @Override public void onCheckedChange(boolean isChecked) { super.onCheckedChange(isChecked); if (isChecked) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_square_selected, null)); } else { setBackgroundDrawable(getResources().getDrawable(R.drawable.indicator_square_selected)); } } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.indicator_square_unselected, null)); } else { setBackgroundDrawable(getResources().getDrawable(R.drawable.indicator_square_unselected)); } } } } ================================================ FILE: bannerslider/src/main/java/ss/com/bannerslider/viewholder/ImageSlideViewHolder.java ================================================ package ss.com.bannerslider.viewholder; import android.support.annotation.DrawableRes; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.ImageView; import ss.com.bannerslider.Slider; public class ImageSlideViewHolder extends RecyclerView.ViewHolder { public ImageView imageView; public ImageSlideViewHolder(View itemView) { super(itemView); this.imageView = (ImageView) itemView; } public void bindImageSlide(String imageUrl) { if (imageUrl != null) { Slider.getImageLoadingService().loadImage(imageUrl, imageView); } } public void bindImageSlide(@DrawableRes int imageResourceId) { Slider.getImageLoadingService().loadImage(imageResourceId, imageView); } public void bindImageSlide(String url, @DrawableRes int placeHolder, @DrawableRes int error) { Slider.getImageLoadingService().loadImage(url, placeHolder, error, imageView); } } ================================================ FILE: bannerslider/src/main/res/drawable/indicator_circle_selected.xml ================================================ ================================================ FILE: bannerslider/src/main/res/drawable/indicator_circle_unselected.xml ================================================ ================================================ FILE: bannerslider/src/main/res/drawable/indicator_dash_selected.xml ================================================ ================================================ FILE: bannerslider/src/main/res/drawable/indicator_dash_unselected.xml ================================================ ================================================ FILE: bannerslider/src/main/res/drawable/indicator_round_square_selected.xml ================================================ ================================================ FILE: bannerslider/src/main/res/drawable/indicator_round_square_unselected.xml ================================================ ================================================ FILE: bannerslider/src/main/res/drawable/indicator_square_selected.xml ================================================ ================================================ FILE: bannerslider/src/main/res/drawable/indicator_square_unselected.xml ================================================ ================================================ FILE: bannerslider/src/main/res/layout/item_slide_image.xml ================================================ ================================================ FILE: bannerslider/src/main/res/values/attrs.xml ================================================ ================================================ FILE: bannerslider/src/main/res/values/colors.xml ================================================ #eeee #66eeeeee ================================================ FILE: bannerslider/src/main/res/values/dimens.xml ================================================ 8dp 5dp 12dp 2dp 16dp ================================================ FILE: bannerslider/src/main/res/values/strings.xml ================================================ BannerSlider ================================================ FILE: build.gradle ================================================ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.0.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() jcenter() } } task clean(type: Delete) { delete rootProject.buildDir } ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ #Wed Apr 04 15:05:26 IRDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip ================================================ FILE: gradle.properties ================================================ ## Project-wide Gradle settings. # # 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: -Xmx1024m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # # 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 #Sat Apr 07 10:07:45 IRDT 2018 systemProp.http.proxyPassword= systemProp.http.proxyHost=92.222.252.193 org.gradle.jvmargs=-Xmx1536m systemProp.http.proxyUser=s.shahini systemProp.http.proxyPort=6060 ================================================ FILE: gradlew ================================================ #!/usr/bin/env bash ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn ( ) { echo "$*" } die ( ) { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; esac # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules function splitJvmOpts() { JVM_OPTS=("$@") } eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" ================================================ FILE: gradlew.bat ================================================ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windowz variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* goto execute :4NT_args @rem Get arguments from the 4NT Shell from JP Software set CMD_LINE_ARGS=%$ :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: settings.gradle ================================================ include ':app', ':bannerslider'