├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── build.gradle ├── demo ├── .gitignore ├── build.gradle ├── proguard-rules.txt └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── nemo.jpg │ ├── toystory.jpg │ ├── up.jpg │ └── wall.jpg │ ├── java │ └── com │ │ └── daimajia │ │ └── slider │ │ └── demo │ │ ├── ChildAnimationExample.java │ │ ├── MainActivity.java │ │ └── TransformerAdapter.java │ └── res │ ├── drawable-hdpi │ ├── bigbang.jpg │ ├── bird.png │ ├── d1.png │ ├── game_of_thrones.jpg │ ├── hannibal.jpg │ ├── house.jpg │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── layout │ ├── activity_main.xml │ └── item.xml │ ├── menu │ └── main.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── gradle-mvn-push.gradle ├── gradle.properties ├── proguard-rules.txt └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── daimajia │ │ └── slider │ │ └── library │ │ ├── Animations │ │ ├── BaseAnimationInterface.java │ │ └── DescriptionAnimation.java │ │ ├── Indicators │ │ └── PagerIndicator.java │ │ ├── SliderAdapter.java │ │ ├── SliderLayout.java │ │ ├── SliderTypes │ │ ├── BaseSliderView.java │ │ ├── DefaultSliderView.java │ │ └── TextSliderView.java │ │ ├── Transformers │ │ ├── AccordionTransformer.java │ │ ├── BackgroundToForegroundTransformer.java │ │ ├── BaseTransformer.java │ │ ├── CubeInTransformer.java │ │ ├── DefaultTransformer.java │ │ ├── DepthPageTransformer.java │ │ ├── FadeTransformer.java │ │ ├── FlipHorizontalTransformer.java │ │ ├── FlipPageViewTransformer.java │ │ ├── ForegroundToBackgroundTransformer.java │ │ ├── RotateDownTransformer.java │ │ ├── RotateUpTransformer.java │ │ ├── StackTransformer.java │ │ ├── TabletTransformer.java │ │ ├── ZoomInTransformer.java │ │ ├── ZoomOutSlideTransformer.java │ │ └── ZoomOutTransformer.java │ │ └── Tricks │ │ ├── FixedSpeedScroller.java │ │ ├── InfinitePagerAdapter.java │ │ ├── InfiniteViewPager.java │ │ └── ViewPagerEx.java │ └── res │ ├── drawable │ └── indicator_corner_bg.xml │ ├── layout │ ├── indicator_layout.xml │ ├── render_type_default.xml │ ├── render_type_text.xml │ └── slider_layout.xml │ └── values │ ├── attrs.xml │ ├── strings.xml │ └── styles.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | .DS_Store 11 | 12 | # generated files 13 | bin/ 14 | gen/ 15 | Wiki/ 16 | 17 | # Local configuration file (sdk path, etc) 18 | local.properties 19 | 20 | # Eclipse project files 21 | .classpath 22 | .project 23 | .settings/ 24 | 25 | # Proguard folder generated by Eclipse 26 | proguard/ 27 | 28 | #Android Studio 29 | build/ 30 | 31 | # Intellij project files 32 | *.iml 33 | *.ipr 34 | *.iws 35 | .idea/ 36 | 37 | #gradle 38 | .gradle/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | android: 3 | components: 4 | # Uncomment the lines below if you want to 5 | # use the latest revision of Android SDK Tools 6 | # - platform-tools 7 | # - tools 8 | 9 | # The BuildTools version used by your project 10 | - build-tools-22.0.1 11 | 12 | # The SDK version used to compile your project 13 | - android-22 14 | 15 | # Additional components 16 | - extra-google-google_play_services 17 | - extra-google-m2repository 18 | - extra-android-m2repository 19 | - addon-google_apis-google-19 20 | 21 | # Specify at least one system image, 22 | # if you need to run emulator(s) during your tests 23 | - sys-img-armeabi-v7a-android-19 24 | - sys-img-x86-android-17 25 | script: ./gradlew assembleDebug 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android Image Slider [![Build Status](https://travis-ci.org/daimajia/AndroidImageSlider.svg)](https://travis-ci.org/daimajia/AndroidImageSlider) 2 | 3 | [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/daimajia/AndroidImageSlider?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | This is an amazing image slider for the Android platform. I decided to open source this because there is really not an attractive, convenient slider widget in Android. 6 | 7 | You can easily load images from an internet URL, drawable, or file. And there are many kinds of amazing animations you can choose. :-D 8 | 9 | ## Demo 10 | 11 | ![](http://ww3.sinaimg.cn/mw690/610dc034jw1egzor66ojdg20950fknpe.gif) 12 | 13 | [Download Apk](https://github.com/daimajia/AndroidImageSlider/releases/download/v1.0.8/demo-1.0.8.apk) 14 | 15 | ## Usage 16 | 17 | ### Step 1 18 | 19 | #### Gradle 20 | 21 | ```groovy 22 | dependencies { 23 | compile "com.android.support:support-v4:+" 24 | compile 'com.squareup.picasso:picasso:2.3.2' 25 | compile 'com.nineoldandroids:library:2.4.0' 26 | compile 'com.daimajia.slider:library:1.1.5@aar' 27 | } 28 | ``` 29 | 30 | 31 | #### Maven 32 | 33 | ```xml 34 | 35 | com.squareup.picasso 36 | picasso 37 | 2.3.2 38 | 39 | 40 | com.nineoldandroids 41 | library 42 | 2.4.0 43 | 44 | 45 | com.daimajia.slider 46 | library 47 | 1.1.2 48 | apklib 49 | 50 | ``` 51 | 52 | #### Eclipse 53 | 54 | For Eclipse users, I provided a sample project which orgnized as Eclipse way. You can download it from [here](https://github.com/daimajia/AndroidImageSlider/releases/download/v1.0.9/AndroidImageSlider-Eclipse.zip), and make some changes to fit your project. 55 | 56 | Notice: It's the version of 1.0.9, it may not update any more. You can update manually by yourself. 57 | 58 | ### Step 2 59 | 60 | Add permissions (if necessary) to your `AndroidManifest.xml` 61 | 62 | ```xml 63 | 64 | 65 | 66 | 67 | 68 | ``` 69 | 70 | **Note:** If you want to load images from the internet, you need both the `INTERNET` and `READ_EXTERNAL_STORAGE` permissions to allow files from the internet to be cached into local storage. 71 | 72 | If you want to load images from drawable, then no additional permissions are necessary. 73 | 74 | ### Step 3 75 | 76 | Add the Slider to your layout: 77 | 78 | ```java 79 | 84 | ``` 85 | 86 | There are some default indicators. If you want to use a provided indicator: 87 | 88 | ```java 89 | 95 | ``` 96 | 97 | [Code example](https://github.com/daimajia/AndroidImageSlider/blob/master/demo%2Fsrc%2Fmain%2Fjava%2Fcom%2Fdaimajia%2Fslider%2Fdemo%2FMainActivity.java) 98 | 99 | ==== 100 | 101 | ## Advanced usage 102 | 103 | Please visit [Wiki](https://github.com/daimajia/AndroidImageSlider/wiki) 104 | 105 | ## Thanks 106 | 107 | - [Picasso](https://github.com/square/picasso) 108 | - [NineOldAndroids](https://github.com/JakeWharton/NineOldAndroids) 109 | - [ViewPagerTransforms](https://github.com/ToxicBakery/ViewPagerTransforms) 110 | 111 | ##About me 112 | 113 | I am a student in mainland China. I love Google, love Android, love everything that is interesting. If you get any problems when using this library or you have an internship opportunity, please feel free to [email me](mailto:daimajia@gmail.com). :smiley: 114 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | task wrapper(type: Wrapper) { 4 | gradleVersion = '2.2.1' 5 | } 6 | 7 | buildscript { 8 | repositories { 9 | mavenCentral() 10 | } 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:1.1.2' 13 | classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.10.+' 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | mavenCentral() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /demo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'android-sdk-manager' 2 | apply plugin: 'com.android.application' 3 | 4 | 5 | android { 6 | compileSdkVersion 22 7 | buildToolsVersion "22.0.1" 8 | 9 | defaultConfig { 10 | minSdkVersion 8 11 | targetSdkVersion 22 12 | versionCode 2 13 | versionName "1.0.1" 14 | } 15 | buildTypes { 16 | release { 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile project(':library') 25 | compile 'com.android.support:appcompat-v7:22.+' 26 | compile 'com.nineoldandroids:library:2.4.0' 27 | compile 'com.daimajia.androidanimations:library:1.0.3@aar' 28 | } 29 | -------------------------------------------------------------------------------- /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 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /demo/src/main/assets/nemo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/assets/nemo.jpg -------------------------------------------------------------------------------- /demo/src/main/assets/toystory.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/assets/toystory.jpg -------------------------------------------------------------------------------- /demo/src/main/assets/up.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/assets/up.jpg -------------------------------------------------------------------------------- /demo/src/main/assets/wall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/assets/wall.jpg -------------------------------------------------------------------------------- /demo/src/main/java/com/daimajia/slider/demo/ChildAnimationExample.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.demo; 2 | 3 | import android.util.Log; 4 | import android.view.View; 5 | 6 | import com.daimajia.androidanimations.library.attention.StandUpAnimator; 7 | import com.daimajia.slider.library.Animations.BaseAnimationInterface; 8 | 9 | public class ChildAnimationExample implements BaseAnimationInterface { 10 | 11 | private final static String TAG = "ChildAnimationExample"; 12 | 13 | @Override 14 | public void onPrepareCurrentItemLeaveScreen(View current) { 15 | View descriptionLayout = current.findViewById(com.daimajia.slider.library.R.id.description_layout); 16 | if(descriptionLayout!=null){ 17 | current.findViewById(com.daimajia.slider.library.R.id.description_layout).setVisibility(View.INVISIBLE); 18 | } 19 | Log.e(TAG,"onPrepareCurrentItemLeaveScreen called"); 20 | } 21 | 22 | @Override 23 | public void onPrepareNextItemShowInScreen(View next) { 24 | View descriptionLayout = next.findViewById(com.daimajia.slider.library.R.id.description_layout); 25 | if(descriptionLayout!=null){ 26 | next.findViewById(com.daimajia.slider.library.R.id.description_layout).setVisibility(View.INVISIBLE); 27 | } 28 | Log.e(TAG,"onPrepareNextItemShowInScreen called"); 29 | } 30 | 31 | @Override 32 | public void onCurrentItemDisappear(View view) { 33 | Log.e(TAG,"onCurrentItemDisappear called"); 34 | } 35 | 36 | @Override 37 | public void onNextItemAppear(View view) { 38 | 39 | View descriptionLayout = view.findViewById(com.daimajia.slider.library.R.id.description_layout); 40 | if(descriptionLayout!=null){ 41 | view.findViewById(com.daimajia.slider.library.R.id.description_layout).setVisibility(View.VISIBLE); 42 | // ValueAnimator animator = ObjectAnimator.ofFloat( 43 | // descriptionLayout, "y", -descriptionLayout.getHeight(), 44 | // 0).setDuration(500); 45 | // animator.start(); 46 | // new BounceInAnimator().animate(descriptionLayout); 47 | new StandUpAnimator().animate(descriptionLayout); 48 | } 49 | Log.e(TAG,"onCurrentItemDisappear called"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /demo/src/main/java/com/daimajia/slider/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.demo; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.support.v7.app.ActionBarActivity; 7 | import android.util.Log; 8 | import android.view.Menu; 9 | import android.view.MenuInflater; 10 | import android.view.MenuItem; 11 | import android.view.View; 12 | import android.widget.AdapterView; 13 | import android.widget.ListView; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import com.daimajia.slider.library.Animations.DescriptionAnimation; 18 | import com.daimajia.slider.library.Indicators.PagerIndicator; 19 | import com.daimajia.slider.library.SliderLayout; 20 | import com.daimajia.slider.library.SliderTypes.BaseSliderView; 21 | import com.daimajia.slider.library.SliderTypes.TextSliderView; 22 | import com.daimajia.slider.library.Tricks.ViewPagerEx; 23 | 24 | import java.util.HashMap; 25 | 26 | 27 | public class MainActivity extends ActionBarActivity implements BaseSliderView.OnSliderClickListener, ViewPagerEx.OnPageChangeListener{ 28 | 29 | private SliderLayout mDemoSlider; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_main); 35 | mDemoSlider = (SliderLayout)findViewById(R.id.slider); 36 | 37 | HashMap url_maps = new HashMap(); 38 | url_maps.put("Hannibal", "http://static2.hypable.com/wp-content/uploads/2013/12/hannibal-season-2-release-date.jpg"); 39 | url_maps.put("Big Bang Theory", "http://tvfiles.alphacoders.com/100/hdclearart-10.png"); 40 | url_maps.put("House of Cards", "http://cdn3.nflximg.net/images/3093/2043093.jpg"); 41 | url_maps.put("Game of Thrones", "http://images.boomsbeat.com/data/images/full/19640/game-of-thrones-season-4-jpg.jpg"); 42 | 43 | HashMap file_maps = new HashMap(); 44 | file_maps.put("Hannibal",R.drawable.hannibal); 45 | file_maps.put("Big Bang Theory",R.drawable.bigbang); 46 | file_maps.put("House of Cards",R.drawable.house); 47 | file_maps.put("Game of Thrones", R.drawable.game_of_thrones); 48 | 49 | for(String name : file_maps.keySet()){ 50 | TextSliderView textSliderView = new TextSliderView(this); 51 | // initialize a SliderLayout 52 | textSliderView 53 | .description(name) 54 | .image(file_maps.get(name)) 55 | .setScaleType(BaseSliderView.ScaleType.Fit) 56 | .setOnSliderClickListener(this); 57 | 58 | //add your extra information 59 | textSliderView.bundle(new Bundle()); 60 | textSliderView.getBundle() 61 | .putString("extra",name); 62 | 63 | mDemoSlider.addSlider(textSliderView); 64 | } 65 | mDemoSlider.setPresetTransformer(SliderLayout.Transformer.Accordion); 66 | mDemoSlider.setPresetIndicator(SliderLayout.PresetIndicators.Center_Bottom); 67 | mDemoSlider.setCustomAnimation(new DescriptionAnimation()); 68 | mDemoSlider.setDuration(4000); 69 | mDemoSlider.addOnPageChangeListener(this); 70 | ListView l = (ListView)findViewById(R.id.transformers); 71 | l.setAdapter(new TransformerAdapter(this)); 72 | l.setOnItemClickListener(new AdapterView.OnItemClickListener() { 73 | @Override 74 | public void onItemClick(AdapterView parent, View view, int position, long id) { 75 | mDemoSlider.setPresetTransformer(((TextView) view).getText().toString()); 76 | Toast.makeText(MainActivity.this, ((TextView) view).getText().toString(), Toast.LENGTH_SHORT).show(); 77 | } 78 | }); 79 | 80 | 81 | } 82 | 83 | @Override 84 | protected void onStop() { 85 | // To prevent a memory leak on rotation, make sure to call stopAutoCycle() on the slider before activity or fragment is destroyed 86 | mDemoSlider.stopAutoCycle(); 87 | super.onStop(); 88 | } 89 | 90 | @Override 91 | public void onSliderClick(BaseSliderView slider) { 92 | Toast.makeText(this,slider.getBundle().get("extra") + "",Toast.LENGTH_SHORT).show(); 93 | } 94 | 95 | @Override 96 | public boolean onCreateOptionsMenu(Menu menu) { 97 | MenuInflater menuInflater = getMenuInflater(); 98 | menuInflater.inflate(R.menu.main,menu); 99 | return super.onCreateOptionsMenu(menu); 100 | } 101 | 102 | @Override 103 | public boolean onOptionsItemSelected(MenuItem item) { 104 | switch (item.getItemId()){ 105 | case R.id.action_custom_indicator: 106 | mDemoSlider.setCustomIndicator((PagerIndicator) findViewById(R.id.custom_indicator)); 107 | break; 108 | case R.id.action_custom_child_animation: 109 | mDemoSlider.setCustomAnimation(new ChildAnimationExample()); 110 | break; 111 | case R.id.action_restore_default: 112 | mDemoSlider.setPresetIndicator(SliderLayout.PresetIndicators.Center_Bottom); 113 | mDemoSlider.setCustomAnimation(new DescriptionAnimation()); 114 | break; 115 | case R.id.action_github: 116 | Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/daimajia/AndroidImageSlider")); 117 | startActivity(browserIntent); 118 | break; 119 | } 120 | return super.onOptionsItemSelected(item); 121 | } 122 | 123 | @Override 124 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} 125 | 126 | @Override 127 | public void onPageSelected(int position) { 128 | Log.d("Slider Demo", "Page Changed: " + position); 129 | } 130 | 131 | @Override 132 | public void onPageScrollStateChanged(int state) {} 133 | } 134 | -------------------------------------------------------------------------------- /demo/src/main/java/com/daimajia/slider/demo/TransformerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.demo; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | import android.widget.TextView; 9 | 10 | import com.daimajia.slider.library.SliderLayout; 11 | 12 | /** 13 | * Created by daimajia on 14-5-29. 14 | */ 15 | public class TransformerAdapter extends BaseAdapter{ 16 | private Context mContext; 17 | public TransformerAdapter(Context context) { 18 | mContext = context; 19 | } 20 | 21 | @Override 22 | public int getCount() { 23 | return SliderLayout.Transformer.values().length; 24 | } 25 | 26 | @Override 27 | public Object getItem(int position) { 28 | return SliderLayout.Transformer.values()[position].toString(); 29 | } 30 | 31 | @Override 32 | public long getItemId(int position) { 33 | return position; 34 | } 35 | 36 | @Override 37 | public View getView(int position, View convertView, ViewGroup parent) { 38 | TextView t = (TextView)LayoutInflater.from(mContext).inflate(R.layout.item,null); 39 | t.setText(getItem(position).toString()); 40 | return t; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/bigbang.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/res/drawable-hdpi/bigbang.jpg -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/bird.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/res/drawable-hdpi/bird.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/d1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/res/drawable-hdpi/d1.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/game_of_thrones.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/res/drawable-hdpi/game_of_thrones.jpg -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/hannibal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/res/drawable-hdpi/hannibal.jpg -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/house.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/res/drawable-hdpi/house.jpg -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/demo/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 8 | 16 | 17 | 38 | 45 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /demo/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 5 | 9 | 13 | 17 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /demo/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /demo/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AndroidImageSlider 5 | Hello world! 6 | Settings 7 | 8 | 9 | -------------------------------------------------------------------------------- /demo/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Settings specified in this file will override any Gradle settings 5 | # configured through the IDE. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | 21 | VERSION_NAME=1.1.2 22 | VERSION_CODE=13 23 | GROUP=com.daimajia.slider 24 | 25 | POM_DESCRIPTION=An amazing and convenient Android image slider. 26 | POM_URL=https://github.com/daimajia/AndroidImageSlider 27 | POM_SCM_URL=https://github.com/daimajia/AndroidImageSlider 28 | POM_SCM_CONNECTION=scm:https://github.com/daimajia/AndroidImageSlider.git 29 | POM_SCM_DEV_CONNECTION=scm:https://github.com/daimajia/AndroidImageSlider.git 30 | POM_LICENCE_NAME=MIT 31 | POM_LICENCE_URL=http://opensource.org/licenses/MIT 32 | POM_LICENCE_DIST=repo 33 | POM_DEVELOPER_ID=daimajia 34 | POM_DEVELOPER_NAME=daimajia -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimajia/AndroidImageSlider/e318cabdef668de985efdcc45ca304e2ac6f58b5/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun May 03 23:34:25 CST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 8 9 | targetSdkVersion 22 10 | versionCode 15 11 | versionName "1.1.5" 12 | } 13 | buildTypes { 14 | release { 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 16 | } 17 | } 18 | lintOptions { 19 | abortOnError false 20 | } 21 | } 22 | 23 | dependencies { 24 | compile fileTree(dir: 'libs', include: ['*.jar']) 25 | compile 'com.android.support:appcompat-v7:22.1.1' 26 | compile "com.android.support:support-v4:22.1.1" 27 | compile 'com.squareup.picasso:picasso:2.5.2' 28 | compile 'com.nineoldandroids:library:2.4.0' 29 | } 30 | apply from: './gradle-mvn-push.gradle' 31 | -------------------------------------------------------------------------------- /library/gradle-mvn-push.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Chris Banes 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | apply plugin: 'maven' 18 | apply plugin: 'signing' 19 | 20 | def isReleaseBuild() { 21 | return VERSION_NAME.contains("SNAPSHOT") == false 22 | } 23 | 24 | def getReleaseRepositoryUrl() { 25 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL 26 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" 27 | } 28 | 29 | def getSnapshotRepositoryUrl() { 30 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL 31 | : "https://oss.sonatype.org/content/repositories/snapshots/" 32 | } 33 | 34 | def getRepositoryUsername() { 35 | return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" 36 | } 37 | 38 | def getRepositoryPassword() { 39 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" 40 | } 41 | 42 | afterEvaluate { project -> 43 | uploadArchives { 44 | repositories { 45 | mavenDeployer { 46 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 47 | 48 | pom.groupId = GROUP 49 | pom.artifactId = POM_ARTIFACT_ID 50 | pom.version = VERSION_NAME 51 | 52 | repository(url: getReleaseRepositoryUrl()) { 53 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 54 | } 55 | snapshotRepository(url: getSnapshotRepositoryUrl()) { 56 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 57 | } 58 | 59 | pom.project { 60 | name POM_NAME 61 | packaging POM_PACKAGING 62 | description POM_DESCRIPTION 63 | url POM_URL 64 | 65 | scm { 66 | url POM_SCM_URL 67 | connection POM_SCM_CONNECTION 68 | developerConnection POM_SCM_DEV_CONNECTION 69 | } 70 | 71 | licenses { 72 | license { 73 | name POM_LICENCE_NAME 74 | url POM_LICENCE_URL 75 | distribution POM_LICENCE_DIST 76 | } 77 | } 78 | 79 | developers { 80 | developer { 81 | id POM_DEVELOPER_ID 82 | name POM_DEVELOPER_NAME 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | 90 | signing { 91 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } 92 | sign configurations.archives 93 | } 94 | 95 | task apklib(type: Zip){ 96 | appendix = extension = 'apklib' 97 | 98 | from 'AndroidManifest.xml' 99 | into('res') { 100 | from 'res' 101 | } 102 | into('src') { 103 | from 'src' 104 | } 105 | } 106 | 107 | 108 | task androidJavadocs(type: Javadoc) { 109 | source = android.sourceSets.main.java.srcDirs 110 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 111 | options.links("http://docs.oracle.com/javase/7/docs/api/"); 112 | options.linksOffline "http://d.android.com/reference","${android.sdkDirectory}/docs/reference" 113 | exclude '**/BuildConfig.java' 114 | exclude '**/R.java' 115 | failOnError = false 116 | } 117 | 118 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { 119 | classifier = 'javadoc' 120 | from androidJavadocs.destinationDir 121 | } 122 | 123 | task androidSourcesJar(type: Jar) { 124 | classifier = 'sources' 125 | from android.sourceSets.main.java.sourceFiles 126 | } 127 | 128 | artifacts { 129 | archives androidSourcesJar 130 | archives androidJavadocsJar 131 | archives apklib 132 | } 133 | } -------------------------------------------------------------------------------- /library/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Settings specified in this file will override any Gradle settings 5 | # configured through the IDE. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | POM_NAME=AndroidImageSlider Library 21 | POM_ARTIFACT_ID=library 22 | POM_PACKAGING=aar 23 | -------------------------------------------------------------------------------- /library/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 | #} -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Animations/BaseAnimationInterface.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Animations; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * This interface gives you chance to inject your own animation or do something when the 7 | * {@link com.daimajia.slider.library.Tricks.ViewPagerEx} animation (PagerTransformer) starts or ends. 8 | * 9 | * 10 | * There are two items you have to know. The first item is the slider you are dragging. This item 11 | * I call it Current Item. The second is the slider that gonna to show. I call that Next Item. 12 | * 13 | * When you start to drag the slider in front of you, onPrepareCurrentItemLeaveScreen() and 14 | * onPrepareNextItemShowInScreen will be called. 15 | * 16 | * When you finish drag, the onCurrentItemDisappear and onNextItemAppear will be invoked. 17 | * 18 | * You can see a demo class {@link com.daimajia.slider.library.Animations.DescriptionAnimation}, 19 | * this class gives the description text an animation. 20 | */ 21 | public interface BaseAnimationInterface { 22 | 23 | /** 24 | * When the current item prepare to start leaving the screen. 25 | * @param current 26 | */ 27 | public void onPrepareCurrentItemLeaveScreen(View current); 28 | 29 | /** 30 | * The next item which will be shown in ViewPager/ 31 | * @param next 32 | */ 33 | public void onPrepareNextItemShowInScreen(View next); 34 | 35 | /** 36 | * Current item totally disappear from screen. 37 | * @param view 38 | */ 39 | public void onCurrentItemDisappear(View view); 40 | 41 | /** 42 | * Next item totally show in screen. 43 | * @param view 44 | */ 45 | public void onNextItemAppear(View view); 46 | } 47 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Animations/DescriptionAnimation.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Animations; 2 | 3 | import android.view.View; 4 | 5 | import com.daimajia.slider.library.R; 6 | import com.nineoldandroids.animation.ObjectAnimator; 7 | import com.nineoldandroids.animation.ValueAnimator; 8 | import com.nineoldandroids.view.ViewHelper; 9 | 10 | /** 11 | * A demo class to show how to use {@link com.daimajia.slider.library.Animations.BaseAnimationInterface} 12 | * to make your custom animation in {@link com.daimajia.slider.library.Tricks.ViewPagerEx.PageTransformer} action. 13 | */ 14 | public class DescriptionAnimation implements BaseAnimationInterface { 15 | 16 | @Override 17 | public void onPrepareCurrentItemLeaveScreen(View current) { 18 | View descriptionLayout = current.findViewById(R.id.description_layout); 19 | if(descriptionLayout!=null){ 20 | current.findViewById(R.id.description_layout).setVisibility(View.INVISIBLE); 21 | } 22 | } 23 | 24 | /** 25 | * When next item is coming to show, let's hide the description layout. 26 | * @param next 27 | */ 28 | @Override 29 | public void onPrepareNextItemShowInScreen(View next) { 30 | View descriptionLayout = next.findViewById(R.id.description_layout); 31 | if(descriptionLayout!=null){ 32 | next.findViewById(R.id.description_layout).setVisibility(View.INVISIBLE); 33 | } 34 | } 35 | 36 | 37 | @Override 38 | public void onCurrentItemDisappear(View view) { 39 | 40 | } 41 | 42 | /** 43 | * When next item show in ViewPagerEx, let's make an animation to show the 44 | * description layout. 45 | * @param view 46 | */ 47 | @Override 48 | public void onNextItemAppear(View view) { 49 | 50 | View descriptionLayout = view.findViewById(R.id.description_layout); 51 | if(descriptionLayout!=null){ 52 | float layoutY = ViewHelper.getY(descriptionLayout); 53 | view.findViewById(R.id.description_layout).setVisibility(View.VISIBLE); 54 | ValueAnimator animator = ObjectAnimator.ofFloat( 55 | descriptionLayout,"y",layoutY + descriptionLayout.getHeight(), 56 | layoutY).setDuration(500); 57 | animator.start(); 58 | } 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Indicators/PagerIndicator.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Indicators; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.database.DataSetObserver; 6 | import android.graphics.Color; 7 | import android.graphics.drawable.Drawable; 8 | import android.graphics.drawable.GradientDrawable; 9 | import android.graphics.drawable.LayerDrawable; 10 | import android.support.v4.view.PagerAdapter; 11 | import android.util.AttributeSet; 12 | import android.view.View; 13 | import android.widget.ImageView; 14 | import android.widget.LinearLayout; 15 | 16 | import com.daimajia.slider.library.R; 17 | import com.daimajia.slider.library.Tricks.InfinitePagerAdapter; 18 | import com.daimajia.slider.library.Tricks.ViewPagerEx; 19 | 20 | import java.util.ArrayList; 21 | 22 | /** 23 | * Pager Indicator. 24 | */ 25 | public class PagerIndicator extends LinearLayout implements ViewPagerEx.OnPageChangeListener{ 26 | 27 | private Context mContext; 28 | 29 | /** 30 | * bind this Indicator with {@link com.daimajia.slider.library.Tricks.ViewPagerEx} 31 | */ 32 | private ViewPagerEx mPager; 33 | 34 | /** 35 | * Variable to remember the previous selected indicator. 36 | */ 37 | private ImageView mPreviousSelectedIndicator; 38 | 39 | /** 40 | * Previous selected indicator position. 41 | */ 42 | private int mPreviousSelectedPosition; 43 | 44 | /** 45 | * Custom selected indicator style resource id. 46 | */ 47 | private int mUserSetUnSelectedIndicatorResId; 48 | 49 | 50 | /** 51 | * Custom unselected indicator style resource id. 52 | */ 53 | private int mUserSetSelectedIndicatorResId; 54 | 55 | private Drawable mSelectedDrawable; 56 | private Drawable mUnselectedDrawable; 57 | 58 | /** 59 | *This value is from {@link com.daimajia.slider.library.SliderAdapter} getRealCount() represent 60 | * 61 | * the indicator count that we should draw. 62 | */ 63 | private int mItemCount = 0; 64 | 65 | private Shape mIndicatorShape = Shape.Oval; 66 | 67 | private IndicatorVisibility mVisibility = IndicatorVisibility.Visible; 68 | 69 | private int mDefaultSelectedColor; 70 | private int mDefaultUnSelectedColor; 71 | 72 | private float mDefaultSelectedWidth; 73 | private float mDefaultSelectedHeight; 74 | 75 | private float mDefaultUnSelectedWidth; 76 | private float mDefaultUnSelectedHeight; 77 | 78 | public enum IndicatorVisibility{ 79 | Visible, 80 | Invisible; 81 | }; 82 | 83 | private GradientDrawable mUnSelectedGradientDrawable; 84 | private GradientDrawable mSelectedGradientDrawable; 85 | 86 | private LayerDrawable mSelectedLayerDrawable; 87 | private LayerDrawable mUnSelectedLayerDrawable; 88 | 89 | private float mPadding_left; 90 | private float mPadding_right; 91 | private float mPadding_top; 92 | private float mPadding_bottom; 93 | 94 | private float mSelectedPadding_Left; 95 | private float mSelectedPadding_Right; 96 | private float mSelectedPadding_Top; 97 | private float mSelectedPadding_Bottom; 98 | 99 | private float mUnSelectedPadding_Left; 100 | private float mUnSelectedPadding_Right; 101 | private float mUnSelectedPadding_Top; 102 | private float mUnSelectedPadding_Bottom; 103 | 104 | /** 105 | * Put all the indicators into a ArrayList, so we can remove them easily. 106 | */ 107 | private ArrayList mIndicators = new ArrayList(); 108 | 109 | 110 | public PagerIndicator(Context context) { 111 | this(context,null); 112 | } 113 | 114 | public PagerIndicator(Context context, AttributeSet attrs) { 115 | super(context, attrs); 116 | 117 | mContext = context; 118 | 119 | final TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.PagerIndicator,0,0); 120 | 121 | int visibility = attributes.getInt(R.styleable.PagerIndicator_visibility,IndicatorVisibility.Visible.ordinal()); 122 | 123 | for(IndicatorVisibility v : IndicatorVisibility.values()){ 124 | if(v.ordinal() == visibility){ 125 | mVisibility = v; 126 | break; 127 | } 128 | } 129 | 130 | int shape = attributes.getInt(R.styleable.PagerIndicator_shape, Shape.Oval.ordinal()); 131 | for(Shape s: Shape.values()){ 132 | if(s.ordinal() == shape){ 133 | mIndicatorShape = s; 134 | break; 135 | } 136 | } 137 | 138 | mUserSetSelectedIndicatorResId = attributes.getResourceId(R.styleable.PagerIndicator_selected_drawable, 139 | 0); 140 | mUserSetUnSelectedIndicatorResId = attributes.getResourceId(R.styleable.PagerIndicator_unselected_drawable, 141 | 0); 142 | 143 | mDefaultSelectedColor = attributes.getColor(R.styleable.PagerIndicator_selected_color, Color.rgb(255, 255, 255)); 144 | mDefaultUnSelectedColor = attributes.getColor(R.styleable.PagerIndicator_unselected_color, Color.argb(33,255,255,255)); 145 | 146 | mDefaultSelectedWidth = attributes.getDimension(R.styleable.PagerIndicator_selected_width,(int)pxFromDp(6)); 147 | mDefaultSelectedHeight = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_selected_height,(int)pxFromDp(6)); 148 | 149 | mDefaultUnSelectedWidth = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_unselected_width,(int)pxFromDp(6)); 150 | mDefaultUnSelectedHeight = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_unselected_height,(int)pxFromDp(6)); 151 | 152 | mSelectedGradientDrawable = new GradientDrawable(); 153 | mUnSelectedGradientDrawable = new GradientDrawable(); 154 | 155 | mPadding_left = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_padding_left,(int)pxFromDp(3)); 156 | mPadding_right = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_padding_right,(int)pxFromDp(3)); 157 | mPadding_top = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_padding_top,(int)pxFromDp(0)); 158 | mPadding_bottom = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_padding_bottom,(int)pxFromDp(0)); 159 | 160 | mSelectedPadding_Left = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_selected_padding_left,(int)mPadding_left); 161 | mSelectedPadding_Right = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_selected_padding_right,(int)mPadding_right); 162 | mSelectedPadding_Top = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_selected_padding_top,(int)mPadding_top); 163 | mSelectedPadding_Bottom = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_selected_padding_bottom,(int)mPadding_bottom); 164 | 165 | mUnSelectedPadding_Left = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_unselected_padding_left,(int)mPadding_left); 166 | mUnSelectedPadding_Right = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_unselected_padding_right,(int)mPadding_right); 167 | mUnSelectedPadding_Top = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_unselected_padding_top,(int)mPadding_top); 168 | mUnSelectedPadding_Bottom = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_unselected_padding_bottom,(int)mPadding_bottom); 169 | 170 | mSelectedLayerDrawable = new LayerDrawable(new Drawable[]{mSelectedGradientDrawable}); 171 | mUnSelectedLayerDrawable = new LayerDrawable(new Drawable[]{mUnSelectedGradientDrawable}); 172 | 173 | 174 | setIndicatorStyleResource(mUserSetSelectedIndicatorResId,mUserSetUnSelectedIndicatorResId); 175 | setDefaultIndicatorShape(mIndicatorShape); 176 | setDefaultSelectedIndicatorSize(mDefaultSelectedWidth,mDefaultSelectedHeight,Unit.Px); 177 | setDefaultUnselectedIndicatorSize(mDefaultUnSelectedWidth,mDefaultUnSelectedHeight,Unit.Px); 178 | setDefaultIndicatorColor(mDefaultSelectedColor, mDefaultUnSelectedColor); 179 | setIndicatorVisibility(mVisibility); 180 | attributes.recycle(); 181 | } 182 | 183 | public enum Shape{ 184 | Oval,Rectangle 185 | } 186 | 187 | /** 188 | * if you are using the default indicator, this method will help you to set the shape of 189 | * indicator, there are two kind of shapes you can set, oval and rect. 190 | * @param shape 191 | */ 192 | public void setDefaultIndicatorShape(Shape shape){ 193 | if(mUserSetSelectedIndicatorResId == 0){ 194 | if(shape == Shape.Oval){ 195 | mSelectedGradientDrawable.setShape(GradientDrawable.OVAL); 196 | }else{ 197 | mSelectedGradientDrawable.setShape(GradientDrawable.RECTANGLE); 198 | } 199 | } 200 | if(mUserSetUnSelectedIndicatorResId == 0){ 201 | if(shape == Shape.Oval){ 202 | mUnSelectedGradientDrawable.setShape(GradientDrawable.OVAL); 203 | }else{ 204 | mUnSelectedGradientDrawable.setShape(GradientDrawable.RECTANGLE); 205 | } 206 | } 207 | resetDrawable(); 208 | } 209 | 210 | 211 | /** 212 | * Set Indicator style. 213 | * @param selected page selected drawable 214 | * @param unselected page unselected drawable 215 | */ 216 | public void setIndicatorStyleResource(int selected, int unselected){ 217 | mUserSetSelectedIndicatorResId = selected; 218 | mUserSetUnSelectedIndicatorResId = unselected; 219 | if(selected == 0){ 220 | mSelectedDrawable = mSelectedLayerDrawable; 221 | }else{ 222 | mSelectedDrawable = mContext.getResources().getDrawable(mUserSetSelectedIndicatorResId); 223 | } 224 | if(unselected == 0){ 225 | mUnselectedDrawable = mUnSelectedLayerDrawable; 226 | }else{ 227 | mUnselectedDrawable = mContext.getResources().getDrawable(mUserSetUnSelectedIndicatorResId); 228 | } 229 | 230 | resetDrawable(); 231 | } 232 | 233 | /** 234 | * if you are using the default indicator , this method will help you to set the selected status and 235 | * the unselected status color. 236 | * @param selectedColor 237 | * @param unselectedColor 238 | */ 239 | public void setDefaultIndicatorColor(int selectedColor,int unselectedColor){ 240 | if(mUserSetSelectedIndicatorResId == 0){ 241 | mSelectedGradientDrawable.setColor(selectedColor); 242 | } 243 | if(mUserSetUnSelectedIndicatorResId == 0){ 244 | mUnSelectedGradientDrawable.setColor(unselectedColor); 245 | } 246 | resetDrawable(); 247 | } 248 | 249 | public enum Unit{ 250 | DP,Px 251 | } 252 | 253 | public void setDefaultSelectedIndicatorSize(float width,float height,Unit unit){ 254 | if(mUserSetSelectedIndicatorResId == 0){ 255 | float w = width; 256 | float h = height; 257 | if(unit == Unit.DP){ 258 | w = pxFromDp(width); 259 | h = pxFromDp(height); 260 | } 261 | mSelectedGradientDrawable.setSize((int) w, (int) h); 262 | resetDrawable(); 263 | } 264 | } 265 | 266 | public void setDefaultUnselectedIndicatorSize(float width,float height,Unit unit){ 267 | if(mUserSetUnSelectedIndicatorResId == 0){ 268 | float w = width; 269 | float h = height; 270 | if(unit == Unit.DP){ 271 | w = pxFromDp(width); 272 | h = pxFromDp(height); 273 | } 274 | mUnSelectedGradientDrawable.setSize((int) w, (int) h); 275 | resetDrawable(); 276 | } 277 | } 278 | 279 | public void setDefaultIndicatorSize(float width, float height, Unit unit){ 280 | setDefaultSelectedIndicatorSize(width,height,unit); 281 | setDefaultUnselectedIndicatorSize(width,height,unit); 282 | } 283 | 284 | private float dpFromPx(float px) 285 | { 286 | return px / this.getContext().getResources().getDisplayMetrics().density; 287 | } 288 | 289 | private float pxFromDp(float dp) 290 | { 291 | return dp * this.getContext().getResources().getDisplayMetrics().density; 292 | } 293 | 294 | /** 295 | * set the visibility of indicator. 296 | * @param visibility 297 | */ 298 | public void setIndicatorVisibility(IndicatorVisibility visibility){ 299 | if(visibility == IndicatorVisibility.Visible){ 300 | setVisibility(View.VISIBLE); 301 | }else{ 302 | setVisibility(View.INVISIBLE); 303 | } 304 | resetDrawable(); 305 | } 306 | 307 | /** 308 | * clear self means unregister the dataset observer and remove all the child views(indicators). 309 | */ 310 | public void destroySelf(){ 311 | if(mPager == null || mPager.getAdapter() == null){ 312 | return; 313 | } 314 | InfinitePagerAdapter wrapper = (InfinitePagerAdapter)mPager.getAdapter(); 315 | PagerAdapter adapter = wrapper.getRealAdapter(); 316 | if(adapter!=null){ 317 | adapter.unregisterDataSetObserver(dataChangeObserver); 318 | } 319 | removeAllViews(); 320 | } 321 | 322 | /** 323 | * bind indicator with viewpagerEx. 324 | * @param pager 325 | */ 326 | public void setViewPager(ViewPagerEx pager){ 327 | if(pager.getAdapter() == null){ 328 | throw new IllegalStateException("Viewpager does not have adapter instance"); 329 | } 330 | mPager = pager; 331 | mPager.addOnPageChangeListener(this); 332 | ((InfinitePagerAdapter)mPager.getAdapter()).getRealAdapter().registerDataSetObserver(dataChangeObserver); 333 | } 334 | 335 | 336 | private void resetDrawable(){ 337 | for(View i : mIndicators){ 338 | if(mPreviousSelectedIndicator!= null && mPreviousSelectedIndicator.equals(i)){ 339 | ((ImageView)i).setImageDrawable(mSelectedDrawable); 340 | } 341 | else{ 342 | ((ImageView)i).setImageDrawable(mUnselectedDrawable); 343 | } 344 | } 345 | } 346 | 347 | /** 348 | * redraw the indicators. 349 | */ 350 | public void redraw(){ 351 | mItemCount = getShouldDrawCount(); 352 | mPreviousSelectedIndicator = null; 353 | for(View i:mIndicators){ 354 | removeView(i); 355 | } 356 | 357 | 358 | for(int i =0 ;i< mItemCount; i++){ 359 | ImageView indicator = new ImageView(mContext); 360 | indicator.setImageDrawable(mUnselectedDrawable); 361 | indicator.setPadding((int)mUnSelectedPadding_Left, 362 | (int)mUnSelectedPadding_Top, 363 | (int)mUnSelectedPadding_Right, 364 | (int)mUnSelectedPadding_Bottom); 365 | addView(indicator); 366 | mIndicators.add(indicator); 367 | } 368 | setItemAsSelected(mPreviousSelectedPosition); 369 | } 370 | 371 | /** 372 | * since we used a adapter wrapper, so we can't getCount directly from wrapper. 373 | * @return 374 | */ 375 | private int getShouldDrawCount(){ 376 | if(mPager.getAdapter() instanceof InfinitePagerAdapter){ 377 | return ((InfinitePagerAdapter)mPager.getAdapter()).getRealCount(); 378 | }else{ 379 | return mPager.getAdapter().getCount(); 380 | } 381 | } 382 | 383 | private DataSetObserver dataChangeObserver = new DataSetObserver() { 384 | @Override 385 | public void onChanged() { 386 | PagerAdapter adapter = mPager.getAdapter(); 387 | int count = 0; 388 | if(adapter instanceof InfinitePagerAdapter){ 389 | count = ((InfinitePagerAdapter)adapter).getRealCount(); 390 | }else{ 391 | count = adapter.getCount(); 392 | } 393 | if(count > mItemCount){ 394 | for(int i =0 ; i< count - mItemCount;i++){ 395 | ImageView indicator = new ImageView(mContext); 396 | indicator.setImageDrawable(mUnselectedDrawable); 397 | indicator.setPadding((int)mUnSelectedPadding_Left, 398 | (int)mUnSelectedPadding_Top, 399 | (int)mUnSelectedPadding_Right, 400 | (int)mUnSelectedPadding_Bottom); 401 | addView(indicator); 402 | mIndicators.add(indicator); 403 | } 404 | }else if(count < mItemCount){ 405 | for(int i = 0; i < mItemCount - count;i++){ 406 | removeView(mIndicators.get(0)); 407 | mIndicators.remove(0); 408 | } 409 | } 410 | mItemCount = count; 411 | mPager.setCurrentItem(mItemCount*20 + mPager.getCurrentItem()); 412 | } 413 | 414 | @Override 415 | public void onInvalidated() { 416 | super.onInvalidated(); 417 | redraw(); 418 | } 419 | }; 420 | 421 | private void setItemAsSelected(int position){ 422 | if(mPreviousSelectedIndicator != null){ 423 | mPreviousSelectedIndicator.setImageDrawable(mUnselectedDrawable); 424 | mPreviousSelectedIndicator.setPadding( 425 | (int)mUnSelectedPadding_Left, 426 | (int)mUnSelectedPadding_Top, 427 | (int)mUnSelectedPadding_Right, 428 | (int)mUnSelectedPadding_Bottom 429 | ); 430 | } 431 | ImageView currentSelected = (ImageView)getChildAt(position + 1); 432 | if(currentSelected != null){ 433 | currentSelected.setImageDrawable(mSelectedDrawable); 434 | currentSelected.setPadding( 435 | (int)mSelectedPadding_Left, 436 | (int)mSelectedPadding_Top, 437 | (int)mSelectedPadding_Right, 438 | (int)mSelectedPadding_Bottom 439 | ); 440 | mPreviousSelectedIndicator = currentSelected; 441 | } 442 | mPreviousSelectedPosition = position; 443 | } 444 | 445 | @Override 446 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 447 | } 448 | 449 | public IndicatorVisibility getIndicatorVisibility(){ 450 | return mVisibility; 451 | } 452 | 453 | @Override 454 | public void onPageSelected(int position) { 455 | if(mItemCount == 0){ 456 | return; 457 | } 458 | setItemAsSelected(position-1); 459 | } 460 | @Override 461 | public void onPageScrollStateChanged(int state) { 462 | } 463 | 464 | public int getSelectedIndicatorResId(){ 465 | return mUserSetSelectedIndicatorResId; 466 | } 467 | 468 | public int getUnSelectedIndicatorResId(){ 469 | return mUserSetUnSelectedIndicatorResId; 470 | } 471 | 472 | } 473 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/SliderAdapter.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.PagerAdapter; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | 8 | import com.daimajia.slider.library.SliderTypes.BaseSliderView; 9 | 10 | import java.util.ArrayList; 11 | 12 | /** 13 | * A slider adapter 14 | */ 15 | public class SliderAdapter extends PagerAdapter implements BaseSliderView.ImageLoadListener{ 16 | 17 | private Context mContext; 18 | private ArrayList mImageContents; 19 | 20 | public SliderAdapter(Context context){ 21 | mContext = context; 22 | mImageContents = new ArrayList(); 23 | } 24 | 25 | public void addSlider(T slider){ 26 | slider.setOnImageLoadListener(this); 27 | mImageContents.add(slider); 28 | notifyDataSetChanged(); 29 | } 30 | 31 | public BaseSliderView getSliderView(int position){ 32 | if(position < 0 || position >= mImageContents.size()){ 33 | return null; 34 | }else{ 35 | return mImageContents.get(position); 36 | } 37 | } 38 | 39 | @Override 40 | public int getItemPosition(Object object) { 41 | return POSITION_NONE; 42 | } 43 | 44 | public void removeSlider(T slider){ 45 | if(mImageContents.contains(slider)){ 46 | mImageContents.remove(slider); 47 | notifyDataSetChanged(); 48 | } 49 | } 50 | 51 | public void removeSliderAt(int position){ 52 | if(mImageContents.size() > position){ 53 | mImageContents.remove(position); 54 | notifyDataSetChanged(); 55 | } 56 | } 57 | 58 | public void removeAllSliders(){ 59 | mImageContents.clear(); 60 | notifyDataSetChanged(); 61 | } 62 | 63 | @Override 64 | public int getCount() { 65 | return mImageContents.size(); 66 | } 67 | 68 | @Override 69 | public boolean isViewFromObject(View view, Object object) { 70 | return view==object; 71 | } 72 | 73 | @Override 74 | public void destroyItem(ViewGroup container, int position, Object object) { 75 | container.removeView((View) object); 76 | } 77 | 78 | @Override 79 | public Object instantiateItem(ViewGroup container, int position) { 80 | BaseSliderView b = mImageContents.get(position); 81 | View v = b.getView(); 82 | container.addView(v); 83 | return v; 84 | } 85 | 86 | @Override 87 | public void onStart(BaseSliderView target) { 88 | 89 | } 90 | 91 | /** 92 | * When image download error, then remove. 93 | * @param result 94 | * @param target 95 | */ 96 | @Override 97 | public void onEnd(boolean result, BaseSliderView target) { 98 | if(target.isErrorDisappear() == false || result == true){ 99 | return; 100 | } 101 | for (BaseSliderView slider: mImageContents){ 102 | if(slider.equals(target)){ 103 | removeSlider(target); 104 | break; 105 | } 106 | } 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/SliderLayout.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.os.Message; 6 | import android.support.v4.view.PagerAdapter; 7 | import android.util.AttributeSet; 8 | import android.view.LayoutInflater; 9 | import android.view.MotionEvent; 10 | import android.view.View; 11 | import android.view.animation.Interpolator; 12 | import android.widget.RelativeLayout; 13 | 14 | import com.daimajia.slider.library.Animations.BaseAnimationInterface; 15 | import com.daimajia.slider.library.Indicators.PagerIndicator; 16 | import com.daimajia.slider.library.SliderTypes.BaseSliderView; 17 | import com.daimajia.slider.library.Transformers.AccordionTransformer; 18 | import com.daimajia.slider.library.Transformers.BackgroundToForegroundTransformer; 19 | import com.daimajia.slider.library.Transformers.BaseTransformer; 20 | import com.daimajia.slider.library.Transformers.CubeInTransformer; 21 | import com.daimajia.slider.library.Transformers.DefaultTransformer; 22 | import com.daimajia.slider.library.Transformers.DepthPageTransformer; 23 | import com.daimajia.slider.library.Transformers.FadeTransformer; 24 | import com.daimajia.slider.library.Transformers.FlipHorizontalTransformer; 25 | import com.daimajia.slider.library.Transformers.FlipPageViewTransformer; 26 | import com.daimajia.slider.library.Transformers.ForegroundToBackgroundTransformer; 27 | import com.daimajia.slider.library.Transformers.RotateDownTransformer; 28 | import com.daimajia.slider.library.Transformers.RotateUpTransformer; 29 | import com.daimajia.slider.library.Transformers.StackTransformer; 30 | import com.daimajia.slider.library.Transformers.TabletTransformer; 31 | import com.daimajia.slider.library.Transformers.ZoomInTransformer; 32 | import com.daimajia.slider.library.Transformers.ZoomOutSlideTransformer; 33 | import com.daimajia.slider.library.Transformers.ZoomOutTransformer; 34 | import com.daimajia.slider.library.Tricks.FixedSpeedScroller; 35 | import com.daimajia.slider.library.Tricks.InfinitePagerAdapter; 36 | import com.daimajia.slider.library.Tricks.InfiniteViewPager; 37 | import com.daimajia.slider.library.Tricks.ViewPagerEx; 38 | 39 | import java.lang.reflect.Field; 40 | import java.util.Timer; 41 | import java.util.TimerTask; 42 | 43 | /** 44 | * SliderLayout is compound layout. This is combined with {@link com.daimajia.slider.library.Indicators.PagerIndicator} 45 | * and {@link com.daimajia.slider.library.Tricks.ViewPagerEx} . 46 | * 47 | * There is some properties you can set in XML: 48 | * 49 | * indicator_visibility 50 | * visible 51 | * invisible 52 | * 53 | * indicator_shape 54 | * oval 55 | * rect 56 | * 57 | * indicator_selected_color 58 | * 59 | * indicator_unselected_color 60 | * 61 | * indicator_selected_drawable 62 | * 63 | * indicator_unselected_drawable 64 | * 65 | * pager_animation 66 | * Default 67 | * Accordion 68 | * Background2Foreground 69 | * CubeIn 70 | * DepthPage 71 | * Fade 72 | * FlipHorizontal 73 | * FlipPage 74 | * Foreground2Background 75 | * RotateDown 76 | * RotateUp 77 | * Stack 78 | * Tablet 79 | * ZoomIn 80 | * ZoomOutSlide 81 | * ZoomOut 82 | * 83 | * pager_animation_span 84 | * 85 | * 86 | */ 87 | public class SliderLayout extends RelativeLayout{ 88 | 89 | private Context mContext; 90 | /** 91 | * InfiniteViewPager is extended from ViewPagerEx. As the name says, it can scroll without bounder. 92 | */ 93 | private InfiniteViewPager mViewPager; 94 | 95 | /** 96 | * InfiniteViewPager adapter. 97 | */ 98 | private SliderAdapter mSliderAdapter; 99 | 100 | /** 101 | * {@link com.daimajia.slider.library.Tricks.ViewPagerEx} indicator. 102 | */ 103 | private PagerIndicator mIndicator; 104 | 105 | 106 | /** 107 | * A timer and a TimerTask using to cycle the {@link com.daimajia.slider.library.Tricks.ViewPagerEx}. 108 | */ 109 | private Timer mCycleTimer; 110 | private TimerTask mCycleTask; 111 | 112 | /** 113 | * For resuming the cycle, after user touch or click the {@link com.daimajia.slider.library.Tricks.ViewPagerEx}. 114 | */ 115 | private Timer mResumingTimer; 116 | private TimerTask mResumingTask; 117 | 118 | /** 119 | * If {@link com.daimajia.slider.library.Tricks.ViewPagerEx} is Cycling 120 | */ 121 | private boolean mCycling; 122 | 123 | /** 124 | * Determine if auto recover after user touch the {@link com.daimajia.slider.library.Tricks.ViewPagerEx} 125 | */ 126 | private boolean mAutoRecover = true; 127 | 128 | private int mTransformerId; 129 | 130 | /** 131 | * {@link com.daimajia.slider.library.Tricks.ViewPagerEx} transformer time span. 132 | */ 133 | private int mTransformerSpan = 1100; 134 | 135 | private boolean mAutoCycle; 136 | 137 | /** 138 | * the duration between animation. 139 | */ 140 | private long mSliderDuration = 4000; 141 | 142 | /** 143 | * Visibility of {@link com.daimajia.slider.library.Indicators.PagerIndicator} 144 | */ 145 | private PagerIndicator.IndicatorVisibility mIndicatorVisibility = PagerIndicator.IndicatorVisibility.Visible; 146 | 147 | /** 148 | * {@link com.daimajia.slider.library.Tricks.ViewPagerEx} 's transformer 149 | */ 150 | private BaseTransformer mViewPagerTransformer; 151 | 152 | /** 153 | * @see com.daimajia.slider.library.Animations.BaseAnimationInterface 154 | */ 155 | private BaseAnimationInterface mCustomAnimation; 156 | 157 | /** 158 | * {@link com.daimajia.slider.library.Indicators.PagerIndicator} shape, rect or oval. 159 | */ 160 | 161 | public SliderLayout(Context context) { 162 | this(context,null); 163 | } 164 | 165 | public SliderLayout(Context context, AttributeSet attrs) { 166 | this(context,attrs,R.attr.SliderStyle); 167 | } 168 | 169 | public SliderLayout(Context context, AttributeSet attrs, int defStyle) { 170 | super(context, attrs, defStyle); 171 | mContext = context; 172 | LayoutInflater.from(context).inflate(R.layout.slider_layout, this, true); 173 | 174 | final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs,R.styleable.SliderLayout, 175 | defStyle,0); 176 | 177 | mTransformerSpan = attributes.getInteger(R.styleable.SliderLayout_pager_animation_span, 1100); 178 | mTransformerId = attributes.getInt(R.styleable.SliderLayout_pager_animation, Transformer.Default.ordinal()); 179 | mAutoCycle = attributes.getBoolean(R.styleable.SliderLayout_auto_cycle,true); 180 | int visibility = attributes.getInt(R.styleable.SliderLayout_indicator_visibility,0); 181 | for(PagerIndicator.IndicatorVisibility v: PagerIndicator.IndicatorVisibility.values()){ 182 | if(v.ordinal() == visibility){ 183 | mIndicatorVisibility = v; 184 | break; 185 | } 186 | } 187 | mSliderAdapter = new SliderAdapter(mContext); 188 | PagerAdapter wrappedAdapter = new InfinitePagerAdapter(mSliderAdapter); 189 | 190 | mViewPager = (InfiniteViewPager)findViewById(R.id.daimajia_slider_viewpager); 191 | mViewPager.setAdapter(wrappedAdapter); 192 | 193 | mViewPager.setOnTouchListener(new OnTouchListener() { 194 | @Override 195 | public boolean onTouch(View v, MotionEvent event) { 196 | int action = event.getAction(); 197 | switch (action) { 198 | case MotionEvent.ACTION_UP: 199 | recoverCycle(); 200 | break; 201 | } 202 | return false; 203 | } 204 | }); 205 | 206 | attributes.recycle(); 207 | setPresetIndicator(PresetIndicators.Center_Bottom); 208 | setPresetTransformer(mTransformerId); 209 | setSliderTransformDuration(mTransformerSpan,null); 210 | setIndicatorVisibility(mIndicatorVisibility); 211 | if(mAutoCycle){ 212 | startAutoCycle(); 213 | } 214 | } 215 | 216 | public void addOnPageChangeListener(ViewPagerEx.OnPageChangeListener onPageChangeListener){ 217 | if(onPageChangeListener != null){ 218 | mViewPager.addOnPageChangeListener(onPageChangeListener); 219 | } 220 | } 221 | 222 | public void removeOnPageChangeListener(ViewPagerEx.OnPageChangeListener onPageChangeListener) { 223 | mViewPager.removeOnPageChangeListener(onPageChangeListener); 224 | } 225 | 226 | public void setCustomIndicator(PagerIndicator indicator){ 227 | if(mIndicator != null){ 228 | mIndicator.destroySelf(); 229 | } 230 | mIndicator = indicator; 231 | mIndicator.setIndicatorVisibility(mIndicatorVisibility); 232 | mIndicator.setViewPager(mViewPager); 233 | mIndicator.redraw(); 234 | } 235 | 236 | public void addSlider(T imageContent){ 237 | mSliderAdapter.addSlider(imageContent); 238 | } 239 | 240 | private android.os.Handler mh = new android.os.Handler(){ 241 | @Override 242 | public void handleMessage(Message msg) { 243 | super.handleMessage(msg); 244 | moveNextPosition(true); 245 | } 246 | }; 247 | 248 | public void startAutoCycle(){ 249 | startAutoCycle(mSliderDuration, mSliderDuration, mAutoRecover); 250 | } 251 | 252 | /** 253 | * start auto cycle. 254 | * @param delay delay time 255 | * @param duration animation duration time. 256 | * @param autoRecover if recover after user touches the slider. 257 | */ 258 | public void startAutoCycle(long delay,long duration,boolean autoRecover){ 259 | if(mCycleTimer != null) mCycleTimer.cancel(); 260 | if(mCycleTask != null) mCycleTask.cancel(); 261 | if(mResumingTask != null) mResumingTask.cancel(); 262 | if(mResumingTimer != null) mResumingTimer.cancel(); 263 | mSliderDuration = duration; 264 | mCycleTimer = new Timer(); 265 | mAutoRecover = autoRecover; 266 | mCycleTask = new TimerTask() { 267 | @Override 268 | public void run() { 269 | mh.sendEmptyMessage(0); 270 | } 271 | }; 272 | mCycleTimer.schedule(mCycleTask,delay,mSliderDuration); 273 | mCycling = true; 274 | mAutoCycle = true; 275 | } 276 | 277 | /** 278 | * pause auto cycle. 279 | */ 280 | private void pauseAutoCycle(){ 281 | if(mCycling){ 282 | mCycleTimer.cancel(); 283 | mCycleTask.cancel(); 284 | mCycling = false; 285 | }else{ 286 | if(mResumingTimer != null && mResumingTask != null){ 287 | recoverCycle(); 288 | } 289 | } 290 | } 291 | 292 | /** 293 | * set the duration between two slider changes. the duration value must >= 500 294 | * @param duration 295 | */ 296 | public void setDuration(long duration){ 297 | if(duration >= 500){ 298 | mSliderDuration = duration; 299 | if(mAutoCycle && mCycling){ 300 | startAutoCycle(); 301 | } 302 | } 303 | } 304 | 305 | /** 306 | * stop the auto circle 307 | */ 308 | public void stopAutoCycle(){ 309 | if(mCycleTask!=null){ 310 | mCycleTask.cancel(); 311 | } 312 | if(mCycleTimer!= null){ 313 | mCycleTimer.cancel(); 314 | } 315 | if(mResumingTimer!= null){ 316 | mResumingTimer.cancel(); 317 | } 318 | if(mResumingTask!=null){ 319 | mResumingTask.cancel(); 320 | } 321 | mAutoCycle = false; 322 | mCycling = false; 323 | } 324 | 325 | /** 326 | * when paused cycle, this method can weak it up. 327 | */ 328 | private void recoverCycle(){ 329 | if(!mAutoRecover || !mAutoCycle){ 330 | return; 331 | } 332 | 333 | if(!mCycling){ 334 | if(mResumingTask != null && mResumingTimer!= null){ 335 | mResumingTimer.cancel(); 336 | mResumingTask.cancel(); 337 | } 338 | mResumingTimer = new Timer(); 339 | mResumingTask = new TimerTask() { 340 | @Override 341 | public void run() { 342 | startAutoCycle(); 343 | } 344 | }; 345 | mResumingTimer.schedule(mResumingTask, 6000); 346 | } 347 | } 348 | 349 | 350 | 351 | @Override 352 | public boolean onInterceptTouchEvent(MotionEvent ev) { 353 | int action = ev.getAction(); 354 | switch (action) { 355 | case MotionEvent.ACTION_DOWN: 356 | pauseAutoCycle(); 357 | break; 358 | } 359 | return false; 360 | } 361 | 362 | /** 363 | * set ViewPager transformer. 364 | * @param reverseDrawingOrder 365 | * @param transformer 366 | */ 367 | public void setPagerTransformer(boolean reverseDrawingOrder,BaseTransformer transformer){ 368 | mViewPagerTransformer = transformer; 369 | mViewPagerTransformer.setCustomAnimationInterface(mCustomAnimation); 370 | mViewPager.setPageTransformer(reverseDrawingOrder,mViewPagerTransformer); 371 | } 372 | 373 | 374 | 375 | /** 376 | * set the duration between two slider changes. 377 | * @param period 378 | * @param interpolator 379 | */ 380 | public void setSliderTransformDuration(int period,Interpolator interpolator){ 381 | try{ 382 | Field mScroller = ViewPagerEx.class.getDeclaredField("mScroller"); 383 | mScroller.setAccessible(true); 384 | FixedSpeedScroller scroller = new FixedSpeedScroller(mViewPager.getContext(),interpolator, period); 385 | mScroller.set(mViewPager,scroller); 386 | }catch (Exception e){ 387 | 388 | } 389 | } 390 | 391 | /** 392 | * preset transformers and their names 393 | */ 394 | public enum Transformer{ 395 | Default("Default"), 396 | Accordion("Accordion"), 397 | Background2Foreground("Background2Foreground"), 398 | CubeIn("CubeIn"), 399 | DepthPage("DepthPage"), 400 | Fade("Fade"), 401 | FlipHorizontal("FlipHorizontal"), 402 | FlipPage("FlipPage"), 403 | Foreground2Background("Foreground2Background"), 404 | RotateDown("RotateDown"), 405 | RotateUp("RotateUp"), 406 | Stack("Stack"), 407 | Tablet("Tablet"), 408 | ZoomIn("ZoomIn"), 409 | ZoomOutSlide("ZoomOutSlide"), 410 | ZoomOut("ZoomOut"); 411 | 412 | private final String name; 413 | 414 | private Transformer(String s){ 415 | name = s; 416 | } 417 | public String toString(){ 418 | return name; 419 | } 420 | 421 | public boolean equals(String other){ 422 | return (other == null)? false:name.equals(other); 423 | } 424 | }; 425 | 426 | /** 427 | * set a preset viewpager transformer by id. 428 | * @param transformerId 429 | */ 430 | public void setPresetTransformer(int transformerId){ 431 | for(Transformer t : Transformer.values()){ 432 | if(t.ordinal() == transformerId){ 433 | setPresetTransformer(t); 434 | break; 435 | } 436 | } 437 | } 438 | 439 | /** 440 | * set preset PagerTransformer via the name of transforemer. 441 | * @param transformerName 442 | */ 443 | public void setPresetTransformer(String transformerName){ 444 | for(Transformer t : Transformer.values()){ 445 | if(t.equals(transformerName)){ 446 | setPresetTransformer(t); 447 | return; 448 | } 449 | } 450 | } 451 | 452 | /** 453 | * Inject your custom animation into PageTransformer, you can know more details in 454 | * {@link com.daimajia.slider.library.Animations.BaseAnimationInterface}, 455 | * and you can see a example in {@link com.daimajia.slider.library.Animations.DescriptionAnimation} 456 | * @param animation 457 | */ 458 | public void setCustomAnimation(BaseAnimationInterface animation){ 459 | mCustomAnimation = animation; 460 | if(mViewPagerTransformer != null){ 461 | mViewPagerTransformer.setCustomAnimationInterface(mCustomAnimation); 462 | } 463 | } 464 | 465 | /** 466 | * pretty much right? enjoy it. :-D 467 | * 468 | * @param ts 469 | */ 470 | public void setPresetTransformer(Transformer ts){ 471 | // 472 | // special thanks to https://github.com/ToxicBakery/ViewPagerTransforms 473 | // 474 | BaseTransformer t = null; 475 | switch (ts){ 476 | case Default: 477 | t = new DefaultTransformer(); 478 | break; 479 | case Accordion: 480 | t = new AccordionTransformer(); 481 | break; 482 | case Background2Foreground: 483 | t = new BackgroundToForegroundTransformer(); 484 | break; 485 | case CubeIn: 486 | t = new CubeInTransformer(); 487 | break; 488 | case DepthPage: 489 | t = new DepthPageTransformer(); 490 | break; 491 | case Fade: 492 | t = new FadeTransformer(); 493 | break; 494 | case FlipHorizontal: 495 | t = new FlipHorizontalTransformer(); 496 | break; 497 | case FlipPage: 498 | t = new FlipPageViewTransformer(); 499 | break; 500 | case Foreground2Background: 501 | t = new ForegroundToBackgroundTransformer(); 502 | break; 503 | case RotateDown: 504 | t = new RotateDownTransformer(); 505 | break; 506 | case RotateUp: 507 | t = new RotateUpTransformer(); 508 | break; 509 | case Stack: 510 | t = new StackTransformer(); 511 | break; 512 | case Tablet: 513 | t = new TabletTransformer(); 514 | break; 515 | case ZoomIn: 516 | t = new ZoomInTransformer(); 517 | break; 518 | case ZoomOutSlide: 519 | t = new ZoomOutSlideTransformer(); 520 | break; 521 | case ZoomOut: 522 | t = new ZoomOutTransformer(); 523 | break; 524 | } 525 | setPagerTransformer(true,t); 526 | } 527 | 528 | 529 | 530 | /** 531 | * Set the visibility of the indicators. 532 | * @param visibility 533 | */ 534 | public void setIndicatorVisibility(PagerIndicator.IndicatorVisibility visibility){ 535 | if(mIndicator == null){ 536 | return; 537 | } 538 | 539 | mIndicator.setIndicatorVisibility(visibility); 540 | } 541 | 542 | public PagerIndicator.IndicatorVisibility getIndicatorVisibility(){ 543 | if(mIndicator == null){ 544 | return mIndicator.getIndicatorVisibility(); 545 | } 546 | return PagerIndicator.IndicatorVisibility.Invisible; 547 | 548 | } 549 | 550 | /** 551 | * get the {@link com.daimajia.slider.library.Indicators.PagerIndicator} instance. 552 | * You can manipulate the properties of the indicator. 553 | * @return 554 | */ 555 | public PagerIndicator getPagerIndicator(){ 556 | return mIndicator; 557 | } 558 | 559 | public enum PresetIndicators{ 560 | Center_Bottom("Center_Bottom",R.id.default_center_bottom_indicator), 561 | Right_Bottom("Right_Bottom",R.id.default_bottom_right_indicator), 562 | Left_Bottom("Left_Bottom",R.id.default_bottom_left_indicator), 563 | Center_Top("Center_Top",R.id.default_center_top_indicator), 564 | Right_Top("Right_Top",R.id.default_center_top_right_indicator), 565 | Left_Top("Left_Top",R.id.default_center_top_left_indicator); 566 | 567 | private final String name; 568 | private final int id; 569 | private PresetIndicators(String name,int id){ 570 | this.name = name; 571 | this.id = id; 572 | } 573 | 574 | public String toString(){ 575 | return name; 576 | } 577 | 578 | public int getResourceId(){ 579 | return id; 580 | } 581 | } 582 | public void setPresetIndicator(PresetIndicators presetIndicator){ 583 | PagerIndicator pagerIndicator = (PagerIndicator)findViewById(presetIndicator.getResourceId()); 584 | setCustomIndicator(pagerIndicator); 585 | } 586 | 587 | private InfinitePagerAdapter getWrapperAdapter(){ 588 | PagerAdapter adapter = mViewPager.getAdapter(); 589 | if(adapter!=null){ 590 | return (InfinitePagerAdapter)adapter; 591 | }else{ 592 | return null; 593 | } 594 | } 595 | 596 | private SliderAdapter getRealAdapter(){ 597 | PagerAdapter adapter = mViewPager.getAdapter(); 598 | if(adapter!=null){ 599 | return ((InfinitePagerAdapter)adapter).getRealAdapter(); 600 | } 601 | return null; 602 | } 603 | 604 | /** 605 | * get the current item position 606 | * @return 607 | */ 608 | public int getCurrentPosition(){ 609 | 610 | if(getRealAdapter() == null) 611 | throw new IllegalStateException("You did not set a slider adapter"); 612 | 613 | return mViewPager.getCurrentItem() % getRealAdapter().getCount(); 614 | 615 | } 616 | 617 | /** 618 | * get current slider. 619 | * @return 620 | */ 621 | public BaseSliderView getCurrentSlider(){ 622 | 623 | if(getRealAdapter() == null) 624 | throw new IllegalStateException("You did not set a slider adapter"); 625 | 626 | int count = getRealAdapter().getCount(); 627 | int realCount = mViewPager.getCurrentItem() % count; 628 | return getRealAdapter().getSliderView(realCount); 629 | } 630 | 631 | /** 632 | * remove the slider at the position. Notice: It's a not perfect method, a very small bug still exists. 633 | */ 634 | public void removeSliderAt(int position){ 635 | if(getRealAdapter()!=null){ 636 | getRealAdapter().removeSliderAt(position); 637 | mViewPager.setCurrentItem(mViewPager.getCurrentItem(),false); 638 | } 639 | } 640 | 641 | /** 642 | * remove all the sliders. Notice: It's a not perfect method, a very small bug still exists. 643 | */ 644 | public void removeAllSliders(){ 645 | if(getRealAdapter()!=null){ 646 | int count = getRealAdapter().getCount(); 647 | getRealAdapter().removeAllSliders(); 648 | //a small bug, but fixed by this trick. 649 | //bug: when remove adapter's all the sliders.some caching slider still alive. 650 | mViewPager.setCurrentItem(mViewPager.getCurrentItem() + count,false); 651 | } 652 | } 653 | 654 | /** 655 | *set current slider 656 | * @param position 657 | */ 658 | public void setCurrentPosition(int position, boolean smooth) { 659 | if (getRealAdapter() == null) 660 | throw new IllegalStateException("You did not set a slider adapter"); 661 | if(position >= getRealAdapter().getCount()){ 662 | throw new IllegalStateException("Item position is not exist"); 663 | } 664 | int p = mViewPager.getCurrentItem() % getRealAdapter().getCount(); 665 | int n = (position - p) + mViewPager.getCurrentItem(); 666 | mViewPager.setCurrentItem(n, smooth); 667 | } 668 | 669 | public void setCurrentPosition(int position) { 670 | setCurrentPosition(position, true); 671 | } 672 | 673 | /** 674 | * move to prev slide. 675 | */ 676 | public void movePrevPosition(boolean smooth) { 677 | 678 | if (getRealAdapter() == null) 679 | throw new IllegalStateException("You did not set a slider adapter"); 680 | 681 | mViewPager.setCurrentItem(mViewPager.getCurrentItem() - 1, smooth); 682 | } 683 | 684 | public void movePrevPosition(){ 685 | movePrevPosition(true); 686 | } 687 | 688 | /** 689 | * move to next slide. 690 | */ 691 | public void moveNextPosition(boolean smooth) { 692 | 693 | if (getRealAdapter() == null) 694 | throw new IllegalStateException("You did not set a slider adapter"); 695 | 696 | mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1, smooth); 697 | } 698 | 699 | public void moveNextPosition() { 700 | moveNextPosition(true); 701 | } 702 | } 703 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/SliderTypes/BaseSliderView.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.SliderTypes; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | 8 | import com.daimajia.slider.library.R; 9 | import com.squareup.picasso.Callback; 10 | import com.squareup.picasso.Picasso; 11 | import com.squareup.picasso.RequestCreator; 12 | 13 | import java.io.File; 14 | 15 | /** 16 | * When you want to make your own slider view, you must extends from this class. 17 | * BaseSliderView provides some useful methods. 18 | * I provide two example: {@link com.daimajia.slider.library.SliderTypes.DefaultSliderView} and 19 | * {@link com.daimajia.slider.library.SliderTypes.TextSliderView} 20 | * if you want to show progressbar, you just need to set a progressbar id as @+id/loading_bar. 21 | */ 22 | public abstract class BaseSliderView { 23 | 24 | protected Context mContext; 25 | 26 | private Bundle mBundle; 27 | 28 | /** 29 | * Error place holder image. 30 | */ 31 | private int mErrorPlaceHolderRes; 32 | 33 | /** 34 | * Empty imageView placeholder. 35 | */ 36 | private int mEmptyPlaceHolderRes; 37 | 38 | private String mUrl; 39 | private File mFile; 40 | private int mRes; 41 | 42 | protected OnSliderClickListener mOnSliderClickListener; 43 | 44 | private boolean mErrorDisappear; 45 | 46 | private ImageLoadListener mLoadListener; 47 | 48 | private String mDescription; 49 | 50 | private Picasso mPicasso; 51 | 52 | /** 53 | * Scale type of the image. 54 | */ 55 | private ScaleType mScaleType = ScaleType.Fit; 56 | 57 | public enum ScaleType{ 58 | CenterCrop, CenterInside, Fit, FitCenterCrop 59 | } 60 | 61 | protected BaseSliderView(Context context) { 62 | mContext = context; 63 | } 64 | 65 | /** 66 | * the placeholder image when loading image from url or file. 67 | * @param resId Image resource id 68 | * @return 69 | */ 70 | public BaseSliderView empty(int resId){ 71 | mEmptyPlaceHolderRes = resId; 72 | return this; 73 | } 74 | 75 | /** 76 | * determine whether remove the image which failed to download or load from file 77 | * @param disappear 78 | * @return 79 | */ 80 | public BaseSliderView errorDisappear(boolean disappear){ 81 | mErrorDisappear = disappear; 82 | return this; 83 | } 84 | 85 | /** 86 | * if you set errorDisappear false, this will set a error placeholder image. 87 | * @param resId image resource id 88 | * @return 89 | */ 90 | public BaseSliderView error(int resId){ 91 | mErrorPlaceHolderRes = resId; 92 | return this; 93 | } 94 | 95 | /** 96 | * the description of a slider image. 97 | * @param description 98 | * @return 99 | */ 100 | public BaseSliderView description(String description){ 101 | mDescription = description; 102 | return this; 103 | } 104 | 105 | /** 106 | * set a url as a image that preparing to load 107 | * @param url 108 | * @return 109 | */ 110 | public BaseSliderView image(String url){ 111 | if(mFile != null || mRes != 0){ 112 | throw new IllegalStateException("Call multi image function," + 113 | "you only have permission to call it once"); 114 | } 115 | mUrl = url; 116 | return this; 117 | } 118 | 119 | /** 120 | * set a file as a image that will to load 121 | * @param file 122 | * @return 123 | */ 124 | public BaseSliderView image(File file){ 125 | if(mUrl != null || mRes != 0){ 126 | throw new IllegalStateException("Call multi image function," + 127 | "you only have permission to call it once"); 128 | } 129 | mFile = file; 130 | return this; 131 | } 132 | 133 | public BaseSliderView image(int res){ 134 | if(mUrl != null || mFile != null){ 135 | throw new IllegalStateException("Call multi image function," + 136 | "you only have permission to call it once"); 137 | } 138 | mRes = res; 139 | return this; 140 | } 141 | 142 | /** 143 | * lets users add a bundle of additional information 144 | * @param bundle 145 | * @return 146 | */ 147 | public BaseSliderView bundle(Bundle bundle){ 148 | mBundle = bundle; 149 | return this; 150 | } 151 | 152 | public String getUrl(){ 153 | return mUrl; 154 | } 155 | 156 | public boolean isErrorDisappear(){ 157 | return mErrorDisappear; 158 | } 159 | 160 | public int getEmpty(){ 161 | return mEmptyPlaceHolderRes; 162 | } 163 | 164 | public int getError(){ 165 | return mErrorPlaceHolderRes; 166 | } 167 | 168 | public String getDescription(){ 169 | return mDescription; 170 | } 171 | 172 | public Context getContext(){ 173 | return mContext; 174 | } 175 | 176 | /** 177 | * set a slider image click listener 178 | * @param l 179 | * @return 180 | */ 181 | public BaseSliderView setOnSliderClickListener(OnSliderClickListener l){ 182 | mOnSliderClickListener = l; 183 | return this; 184 | } 185 | 186 | /** 187 | * When you want to implement your own slider view, please call this method in the end in `getView()` method 188 | * @param v the whole view 189 | * @param targetImageView where to place image 190 | */ 191 | protected void bindEventAndShow(final View v, ImageView targetImageView){ 192 | final BaseSliderView me = this; 193 | 194 | v.setOnClickListener(new View.OnClickListener() { 195 | @Override 196 | public void onClick(View v) { 197 | if(mOnSliderClickListener != null){ 198 | mOnSliderClickListener.onSliderClick(me); 199 | } 200 | } 201 | }); 202 | 203 | if (targetImageView == null) 204 | return; 205 | 206 | if (mLoadListener != null) { 207 | mLoadListener.onStart(me); 208 | } 209 | 210 | Picasso p = (mPicasso != null) ? mPicasso : Picasso.with(mContext); 211 | RequestCreator rq = null; 212 | if(mUrl!=null){ 213 | rq = p.load(mUrl); 214 | }else if(mFile != null){ 215 | rq = p.load(mFile); 216 | }else if(mRes != 0){ 217 | rq = p.load(mRes); 218 | }else{ 219 | return; 220 | } 221 | 222 | if(rq == null){ 223 | return; 224 | } 225 | 226 | if(getEmpty() != 0){ 227 | rq.placeholder(getEmpty()); 228 | } 229 | 230 | if(getError() != 0){ 231 | rq.error(getError()); 232 | } 233 | 234 | switch (mScaleType){ 235 | case Fit: 236 | rq.fit(); 237 | break; 238 | case CenterCrop: 239 | rq.fit().centerCrop(); 240 | break; 241 | case CenterInside: 242 | rq.fit().centerInside(); 243 | break; 244 | } 245 | 246 | rq.into(targetImageView,new Callback() { 247 | @Override 248 | public void onSuccess() { 249 | if(v.findViewById(R.id.loading_bar) != null){ 250 | v.findViewById(R.id.loading_bar).setVisibility(View.INVISIBLE); 251 | } 252 | } 253 | 254 | @Override 255 | public void onError() { 256 | if(mLoadListener != null){ 257 | mLoadListener.onEnd(false,me); 258 | } 259 | if(v.findViewById(R.id.loading_bar) != null){ 260 | v.findViewById(R.id.loading_bar).setVisibility(View.INVISIBLE); 261 | } 262 | } 263 | }); 264 | } 265 | 266 | 267 | 268 | public BaseSliderView setScaleType(ScaleType type){ 269 | mScaleType = type; 270 | return this; 271 | } 272 | 273 | public ScaleType getScaleType(){ 274 | return mScaleType; 275 | } 276 | 277 | /** 278 | * the extended class have to implement getView(), which is called by the adapter, 279 | * every extended class response to render their own view. 280 | * @return 281 | */ 282 | public abstract View getView(); 283 | 284 | /** 285 | * set a listener to get a message , if load error. 286 | * @param l 287 | */ 288 | public void setOnImageLoadListener(ImageLoadListener l){ 289 | mLoadListener = l; 290 | } 291 | 292 | public interface OnSliderClickListener { 293 | public void onSliderClick(BaseSliderView slider); 294 | } 295 | 296 | /** 297 | * when you have some extra information, please put it in this bundle. 298 | * @return 299 | */ 300 | public Bundle getBundle(){ 301 | return mBundle; 302 | } 303 | 304 | public interface ImageLoadListener{ 305 | public void onStart(BaseSliderView target); 306 | public void onEnd(boolean result,BaseSliderView target); 307 | } 308 | 309 | /** 310 | * Get the last instance set via setPicasso(), or null if no user provided instance was set 311 | * 312 | * @return The current user-provided Picasso instance, or null if none 313 | */ 314 | public Picasso getPicasso() { 315 | return mPicasso; 316 | } 317 | 318 | /** 319 | * Provide a Picasso instance to use when loading pictures, this is useful if you have a 320 | * particular HTTP cache you would like to share. 321 | * 322 | * @param picasso The Picasso instance to use, may be null to let the system use the default 323 | * instance 324 | */ 325 | public void setPicasso(Picasso picasso) { 326 | mPicasso = picasso; 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/SliderTypes/DefaultSliderView.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.SliderTypes; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | 8 | import com.daimajia.slider.library.R; 9 | 10 | /** 11 | * a simple slider view, which just show an image. If you want to make your own slider view, 12 | * 13 | * just extend BaseSliderView, and implement getView() method. 14 | */ 15 | public class DefaultSliderView extends BaseSliderView{ 16 | 17 | public DefaultSliderView(Context context) { 18 | super(context); 19 | } 20 | 21 | @Override 22 | public View getView() { 23 | View v = LayoutInflater.from(getContext()).inflate(R.layout.render_type_default,null); 24 | ImageView target = (ImageView)v.findViewById(R.id.daimajia_slider_image); 25 | bindEventAndShow(v, target); 26 | return v; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/SliderTypes/TextSliderView.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.SliderTypes; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import com.daimajia.slider.library.R; 10 | 11 | /** 12 | * This is a slider with a description TextView. 13 | */ 14 | public class TextSliderView extends BaseSliderView{ 15 | public TextSliderView(Context context) { 16 | super(context); 17 | } 18 | 19 | @Override 20 | public View getView() { 21 | View v = LayoutInflater.from(getContext()).inflate(R.layout.render_type_text,null); 22 | ImageView target = (ImageView)v.findViewById(R.id.daimajia_slider_image); 23 | TextView description = (TextView)v.findViewById(R.id.description); 24 | description.setText(getDescription()); 25 | bindEventAndShow(v, target); 26 | return v; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/AccordionTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | /** 4 | * Created by daimajia on 14-5-29. 5 | */ 6 | import android.view.View; 7 | 8 | import com.nineoldandroids.view.ViewHelper; 9 | 10 | public class AccordionTransformer extends BaseTransformer { 11 | 12 | @Override 13 | protected void onTransform(View view, float position) { 14 | ViewHelper.setPivotX(view,position < 0 ? 0 : view.getWidth()); 15 | ViewHelper.setScaleX(view,position < 0 ? 1f + position : 1f - position); 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/BackgroundToForegroundTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class BackgroundToForegroundTransformer extends BaseTransformer { 8 | 9 | @Override 10 | protected void onTransform(View view, float position) { 11 | final float height = view.getHeight(); 12 | final float width = view.getWidth(); 13 | final float scale = min(position < 0 ? 1f : Math.abs(1f - position), 0.5f); 14 | 15 | ViewHelper.setScaleX(view,scale); 16 | ViewHelper.setScaleY(view,scale); 17 | ViewHelper.setPivotX(view,width*0.5f); 18 | ViewHelper.setPivotY(view,height*0.5f); 19 | ViewHelper.setTranslationX(view,position < 0 ? width * position : -width * position * 0.25f); 20 | } 21 | 22 | private static final float min(float val, float min) { 23 | return val < min ? min : val; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/BaseTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.daimajia.slider.library.Animations.BaseAnimationInterface; 6 | import com.daimajia.slider.library.Tricks.ViewPagerEx; 7 | import com.nineoldandroids.view.ViewHelper; 8 | 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | 12 | /** 13 | * This is all transformers father. 14 | * 15 | * BaseTransformer implement {@link com.daimajia.slider.library.Tricks.ViewPagerEx.PageTransformer} 16 | * which is just same as {@link android.support.v4.view.ViewPager.PageTransformer}. 17 | * 18 | * After you call setPageTransformer(), transformPage() will be called by {@link com.daimajia.slider.library.Tricks.ViewPagerEx} 19 | * when your slider are animating. 20 | * 21 | * In onPreTransform() function, that will make {@link com.daimajia.slider.library.Animations.BaseAnimationInterface} 22 | * work. 23 | * 24 | * if you want to make an acceptable transformer, please do not forget to extend from this class. 25 | */ 26 | public abstract class BaseTransformer implements ViewPagerEx.PageTransformer { 27 | 28 | private BaseAnimationInterface mCustomAnimationInterface; 29 | 30 | /** 31 | * Called each {@link #transformPage(View, float)}. 32 | * 33 | * @param view 34 | * @param position 35 | */ 36 | protected abstract void onTransform(View view, float position); 37 | 38 | private HashMap> h = new HashMap>(); 39 | 40 | @Override 41 | public void transformPage(View view, float position) { 42 | onPreTransform(view, position); 43 | onTransform(view, position); 44 | onPostTransform(view, position); 45 | } 46 | 47 | /** 48 | * If the position offset of a fragment is less than negative one or greater than one, returning true will set the 49 | * visibility of the fragment to {@link View#GONE}. Returning false will force the fragment to {@link View#VISIBLE}. 50 | * 51 | * @return 52 | */ 53 | protected boolean hideOffscreenPages() { 54 | return true; 55 | } 56 | 57 | /** 58 | * Indicates if the default animations of the view pager should be used. 59 | * 60 | * @return 61 | */ 62 | protected boolean isPagingEnabled() { 63 | return false; 64 | } 65 | 66 | /** 67 | * Called each {@link #transformPage(View, float)} before {{@link #onTransform(View, float)} is called. 68 | * 69 | * @param view 70 | * @param position 71 | */ 72 | protected void onPreTransform(View view, float position) { 73 | final float width = view.getWidth(); 74 | 75 | ViewHelper.setRotationX(view,0); 76 | ViewHelper.setRotationY(view,0); 77 | ViewHelper.setRotation(view,0); 78 | ViewHelper.setScaleX(view,1); 79 | ViewHelper.setScaleY(view,1); 80 | ViewHelper.setPivotX(view,0); 81 | ViewHelper.setPivotY(view,0); 82 | ViewHelper.setTranslationY(view,0); 83 | ViewHelper.setTranslationX(view,isPagingEnabled() ? 0f : -width * position); 84 | 85 | if (hideOffscreenPages()) { 86 | ViewHelper.setAlpha(view,position <= -1f || position >= 1f ? 0f : 1f); 87 | } else { 88 | ViewHelper.setAlpha(view,1f); 89 | } 90 | if(mCustomAnimationInterface != null){ 91 | if(h.containsKey(view) == false || h.get(view).size() == 1){ 92 | if(position > -1 && position < 1){ 93 | if(h.get(view) == null){ 94 | h.put(view,new ArrayList()); 95 | } 96 | h.get(view).add(position); 97 | if(h.get(view).size() == 2){ 98 | float zero = h.get(view).get(0); 99 | float cha = h.get(view).get(1) - h.get(view).get(0); 100 | if(zero > 0){ 101 | if(cha > -1 && cha < 0){ 102 | //in 103 | mCustomAnimationInterface.onPrepareNextItemShowInScreen(view); 104 | }else{ 105 | //out 106 | mCustomAnimationInterface.onPrepareCurrentItemLeaveScreen(view); 107 | } 108 | }else{ 109 | if(cha > -1 && cha < 0){ 110 | //out 111 | mCustomAnimationInterface.onPrepareCurrentItemLeaveScreen(view); 112 | }else{ 113 | //in 114 | mCustomAnimationInterface.onPrepareNextItemShowInScreen(view); 115 | } 116 | } 117 | } 118 | } 119 | } 120 | } 121 | } 122 | boolean isApp,isDis; 123 | /** 124 | * Called each {@link #transformPage(View, float)} call after {@link #onTransform(View, float)} is finished. 125 | * 126 | * @param view 127 | * @param position 128 | */ 129 | protected void onPostTransform(View view, float position) { 130 | if(mCustomAnimationInterface != null){ 131 | if(position == -1 || position == 1){ 132 | mCustomAnimationInterface.onCurrentItemDisappear(view); 133 | isApp = true; 134 | }else if(position == 0){ 135 | mCustomAnimationInterface.onNextItemAppear(view); 136 | isDis = true; 137 | } 138 | if(isApp && isDis){ 139 | h.clear(); 140 | isApp = false; 141 | isDis = false; 142 | } 143 | } 144 | } 145 | 146 | 147 | public void setCustomAnimationInterface(BaseAnimationInterface animationInterface){ 148 | mCustomAnimationInterface = animationInterface; 149 | } 150 | 151 | } -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/CubeInTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class CubeInTransformer extends BaseTransformer { 8 | 9 | @Override 10 | protected void onTransform(View view, float position) { 11 | // Rotate the fragment on the left or right edge 12 | ViewHelper.setPivotX(view,position > 0 ? 0 : view.getWidth()); 13 | ViewHelper.setPivotY(view,0); 14 | ViewHelper.setRotation(view,-90f * position); 15 | } 16 | 17 | @Override 18 | public boolean isPagingEnabled() { 19 | return true; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/DefaultTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | public class DefaultTransformer extends BaseTransformer { 6 | 7 | @Override 8 | protected void onTransform(View view, float position) { 9 | } 10 | 11 | @Override 12 | public boolean isPagingEnabled() { 13 | return true; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/DepthPageTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class DepthPageTransformer extends BaseTransformer { 8 | 9 | private static final float MIN_SCALE = 0.75f; 10 | 11 | @Override 12 | protected void onTransform(View view, float position) { 13 | if (position <= 0f) { 14 | ViewHelper.setTranslationX(view,0f); 15 | ViewHelper.setScaleX(view,1f); 16 | ViewHelper.setScaleY(view,1f); 17 | } else if (position <= 1f) { 18 | final float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); 19 | ViewHelper.setAlpha(view,1-position); 20 | ViewHelper.setPivotY(view,0.5f * view.getHeight()); 21 | ViewHelper.setTranslationX(view,view.getWidth() * - position); 22 | ViewHelper.setScaleX(view,scaleFactor); 23 | ViewHelper.setScaleY(view,scaleFactor); 24 | } 25 | } 26 | 27 | @Override 28 | protected boolean isPagingEnabled() { 29 | return true; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/FadeTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | /** 8 | * Created by realandylawton on 11/22/13. 9 | */ 10 | public class FadeTransformer extends BaseTransformer { 11 | 12 | @Override 13 | protected void onTransform(View view, float position) { 14 | 15 | // Page is not an immediate sibling, just make transparent 16 | if(position < -1 || position > 1) { 17 | ViewHelper.setAlpha(view,0.6f); 18 | } 19 | // Page is sibling to left or right 20 | else if (position <= 0 || position <= 1) { 21 | 22 | // Calculate alpha. Position is decimal in [-1,0] or [0,1] 23 | float alpha = (position <= 0) ? position + 1 : 1 - position; 24 | ViewHelper.setAlpha(view,alpha); 25 | 26 | } 27 | // Page is active, make fully visible 28 | else if (position == 0) { 29 | ViewHelper.setAlpha(view,1); 30 | } 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/FlipHorizontalTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class FlipHorizontalTransformer extends BaseTransformer { 8 | 9 | @Override 10 | protected void onTransform(View view, float position) { 11 | final float rotation = 180f * position; 12 | ViewHelper.setAlpha(view,rotation > 90f || rotation < -90f ? 0 : 1); 13 | ViewHelper.setPivotY(view,view.getHeight()*0.5f); 14 | ViewHelper.setPivotX(view,view.getWidth() * 0.5f); 15 | ViewHelper.setRotationY(view,rotation); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/FlipPageViewTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.os.Build; 4 | import android.view.View; 5 | 6 | import com.daimajia.slider.library.Tricks.ViewPagerEx; 7 | import com.nineoldandroids.view.ViewHelper; 8 | 9 | public class FlipPageViewTransformer extends BaseTransformer { 10 | 11 | @Override 12 | protected void onTransform(View view, float position) { 13 | float percentage = 1 - Math.abs(position); 14 | if(Build.VERSION.SDK_INT >= 13){ 15 | view.setCameraDistance(12000); 16 | } 17 | setVisibility(view, position); 18 | setTranslation(view); 19 | setSize(view, position, percentage); 20 | setRotation(view, position, percentage); 21 | } 22 | 23 | private void setVisibility(View page, float position) { 24 | if (position < 0.5 && position > -0.5) { 25 | page.setVisibility(View.VISIBLE); 26 | } else { 27 | page.setVisibility(View.INVISIBLE); 28 | } 29 | } 30 | 31 | private void setTranslation(View view) { 32 | ViewPagerEx viewPager = (ViewPagerEx) view.getParent(); 33 | int scroll = viewPager.getScrollX() - view.getLeft(); 34 | ViewHelper.setTranslationX(view,scroll); 35 | } 36 | 37 | private void setSize(View view, float position, float percentage) { 38 | ViewHelper.setScaleX(view,(position != 0 && position != 1) ? percentage : 1); 39 | ViewHelper.setScaleY(view,(position != 0 && position != 1) ? percentage : 1); 40 | } 41 | 42 | private void setRotation(View view, float position, float percentage) { 43 | if (position > 0) { 44 | ViewHelper.setRotationY(view,-180 * (percentage + 1)); 45 | } else { 46 | ViewHelper.setRotationY(view,180 * (percentage + 1)); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/ForegroundToBackgroundTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class ForegroundToBackgroundTransformer extends BaseTransformer { 8 | 9 | @Override 10 | protected void onTransform(View view, float position) { 11 | final float height = view.getHeight(); 12 | final float width = view.getWidth(); 13 | final float scale = min(position > 0 ? 1f : Math.abs(1f + position), 0.5f); 14 | 15 | ViewHelper.setScaleX(view,scale); 16 | ViewHelper.setScaleY(view,scale); 17 | ViewHelper.setPivotX(view,width * 0.5f); 18 | ViewHelper.setPivotY(view,height * 0.5f); 19 | ViewHelper.setTranslationX(view,position > 0 ? width * position : -width * position * 0.25f); 20 | } 21 | 22 | private static final float min(float val, float min) { 23 | return val < min ? min : val; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/RotateDownTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class RotateDownTransformer extends BaseTransformer { 8 | 9 | private static final float ROT_MOD = -15f; 10 | 11 | @Override 12 | protected void onTransform(View view, float position) { 13 | final float width = view.getWidth(); 14 | final float height = view.getHeight(); 15 | final float rotation = ROT_MOD * position * -1.25f; 16 | 17 | ViewHelper.setPivotX(view,width * 0.5f); 18 | ViewHelper.setPivotY(view,height); 19 | ViewHelper.setRotation(view,rotation); 20 | } 21 | 22 | @Override 23 | protected boolean isPagingEnabled() { 24 | return true; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/RotateUpTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class RotateUpTransformer extends BaseTransformer { 8 | 9 | private static final float ROT_MOD = -15f; 10 | 11 | @Override 12 | protected void onTransform(View view, float position) { 13 | final float width = view.getWidth(); 14 | final float rotation = ROT_MOD * position; 15 | 16 | ViewHelper.setPivotX(view,width * 0.5f); 17 | ViewHelper.setPivotY(view,0f); 18 | ViewHelper.setTranslationX(view,0f); 19 | ViewHelper.setRotation(view,rotation); 20 | } 21 | 22 | @Override 23 | protected boolean isPagingEnabled() { 24 | return true; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/StackTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class StackTransformer extends BaseTransformer { 8 | 9 | @Override 10 | protected void onTransform(View view, float position) { 11 | ViewHelper.setTranslationX(view,position < 0 ? 0f : -view.getWidth() * position); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/TabletTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.graphics.Camera; 4 | import android.graphics.Matrix; 5 | import android.view.View; 6 | 7 | import com.nineoldandroids.view.ViewHelper; 8 | 9 | public class TabletTransformer extends BaseTransformer { 10 | 11 | private static final Matrix OFFSET_MATRIX = new Matrix(); 12 | private static final Camera OFFSET_CAMERA = new Camera(); 13 | private static final float[] OFFSET_TEMP_FLOAT = new float[2]; 14 | 15 | @Override 16 | protected void onTransform(View view, float position) { 17 | final float rotation = (position < 0 ? 30f : -30f) * Math.abs(position); 18 | 19 | ViewHelper.setTranslationX(view,getOffsetXForRotation(rotation, view.getWidth(), view.getHeight())); 20 | ViewHelper.setPivotX(view,view.getWidth() * 0.5f); 21 | ViewHelper.setPivotY(view,0); 22 | ViewHelper.setRotationY(view,rotation); 23 | } 24 | 25 | protected static final float getOffsetXForRotation(float degrees, int width, int height) { 26 | OFFSET_MATRIX.reset(); 27 | OFFSET_CAMERA.save(); 28 | OFFSET_CAMERA.rotateY(Math.abs(degrees)); 29 | OFFSET_CAMERA.getMatrix(OFFSET_MATRIX); 30 | OFFSET_CAMERA.restore(); 31 | 32 | OFFSET_MATRIX.preTranslate(-width * 0.5f, -height * 0.5f); 33 | OFFSET_MATRIX.postTranslate(width * 0.5f, height * 0.5f); 34 | OFFSET_TEMP_FLOAT[0] = width; 35 | OFFSET_TEMP_FLOAT[1] = height; 36 | OFFSET_MATRIX.mapPoints(OFFSET_TEMP_FLOAT); 37 | return (width - OFFSET_TEMP_FLOAT[0]) * (degrees > 0.0f ? 1.0f : -1.0f); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/ZoomInTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class ZoomInTransformer extends BaseTransformer { 8 | 9 | @Override 10 | protected void onTransform(View view, float position) { 11 | final float scale = position < 0 ? position + 1f : Math.abs(1f - position); 12 | ViewHelper.setScaleX(view,scale); 13 | ViewHelper.setScaleY(view,scale); 14 | ViewHelper.setPivotX(view,view.getWidth() * 0.5f); 15 | ViewHelper.setPivotY(view,view.getHeight() * 0.5f); 16 | ViewHelper.setAlpha(view,position < -1f || position > 1f ? 0f : 1f - (scale - 1f)); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/ZoomOutSlideTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class ZoomOutSlideTransformer extends BaseTransformer { 8 | 9 | private static final float MIN_SCALE = 0.85f; 10 | private static final float MIN_ALPHA = 0.5f; 11 | 12 | @Override 13 | protected void onTransform(View view, float position) { 14 | if (position >= -1 || position <= 1) { 15 | // Modify the default slide transition to shrink the page as well 16 | final float height = view.getHeight(); 17 | final float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); 18 | final float vertMargin = height * (1 - scaleFactor) / 2; 19 | final float horzMargin = view.getWidth() * (1 - scaleFactor) / 2; 20 | 21 | // Center vertically 22 | ViewHelper.setPivotY(view,0.5f * height); 23 | 24 | 25 | if (position < 0) { 26 | ViewHelper.setTranslationX(view,horzMargin - vertMargin / 2); 27 | } else { 28 | ViewHelper.setTranslationX(view,-horzMargin + vertMargin / 2); 29 | } 30 | 31 | // Scale the page down (between MIN_SCALE and 1) 32 | ViewHelper.setScaleX(view,scaleFactor); 33 | ViewHelper.setScaleY(view,scaleFactor); 34 | 35 | // Fade the page relative to its size. 36 | ViewHelper.setAlpha(view,MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Transformers/ZoomOutTransformer.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Transformers; 2 | 3 | import android.view.View; 4 | 5 | import com.nineoldandroids.view.ViewHelper; 6 | 7 | public class ZoomOutTransformer extends BaseTransformer { 8 | 9 | @Override 10 | protected void onTransform(View view, float position) { 11 | final float scale = 1f + Math.abs(position); 12 | ViewHelper.setScaleX(view,scale); 13 | ViewHelper.setScaleY(view,scale); 14 | ViewHelper.setPivotX(view,view.getWidth() * 0.5f); 15 | ViewHelper.setPivotY(view,view.getWidth() * 0.5f); 16 | ViewHelper.setAlpha(view,position < -1f || position > 1f ? 0f : 1f - (scale - 1f)); 17 | if(position < -0.9){ 18 | //-0.9 to prevent a small bug 19 | ViewHelper.setTranslationX(view,view.getWidth() * position); 20 | } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Tricks/FixedSpeedScroller.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Tricks; 2 | 3 | import android.content.Context; 4 | import android.view.animation.Interpolator; 5 | import android.widget.Scroller; 6 | 7 | public class FixedSpeedScroller extends Scroller { 8 | 9 | private int mDuration = 1000; 10 | 11 | public FixedSpeedScroller(Context context) { 12 | super(context); 13 | } 14 | 15 | public FixedSpeedScroller(Context context, Interpolator interpolator) { 16 | super(context, interpolator); 17 | } 18 | 19 | public FixedSpeedScroller(Context context, Interpolator interpolator, int period){ 20 | this(context,interpolator); 21 | mDuration = period; 22 | } 23 | 24 | @Override 25 | public void startScroll(int startX, int startY, int dx, int dy, int duration) { 26 | // Ignore received duration, use fixed one instead 27 | super.startScroll(startX, startY, dx, dy, mDuration); 28 | } 29 | 30 | @Override 31 | public void startScroll(int startX, int startY, int dx, int dy) { 32 | // Ignore received duration, use fixed one instead 33 | super.startScroll(startX, startY, dx, dy, mDuration); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Tricks/InfinitePagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Tricks; 2 | 3 | import android.os.Parcelable; 4 | import android.support.v4.view.PagerAdapter; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.daimajia.slider.library.SliderAdapter; 10 | 11 | /** 12 | * A PagerAdapter that wraps around another PagerAdapter to handle paging wrap-around. 13 | * Thanks to: https://github.com/antonyt/InfiniteViewPager 14 | */ 15 | public class InfinitePagerAdapter extends PagerAdapter { 16 | 17 | private static final String TAG = "InfinitePagerAdapter"; 18 | private static final boolean DEBUG = false; 19 | 20 | private SliderAdapter adapter; 21 | 22 | public InfinitePagerAdapter(SliderAdapter adapter) { 23 | this.adapter = adapter; 24 | } 25 | 26 | public SliderAdapter getRealAdapter(){ 27 | return this.adapter; 28 | } 29 | 30 | @Override 31 | public int getCount() { 32 | // warning: scrolling to very high values (1,000,000+) results in 33 | // strange drawing behaviour 34 | return Integer.MAX_VALUE; 35 | } 36 | 37 | /** 38 | * @return the {@link #getCount()} result of the wrapped adapter 39 | */ 40 | public int getRealCount() { 41 | return adapter.getCount(); 42 | } 43 | 44 | @Override 45 | public Object instantiateItem(ViewGroup container, int position) { 46 | if(getRealCount() == 0){ 47 | return null; 48 | } 49 | int virtualPosition = position % getRealCount(); 50 | debug("instantiateItem: real position: " + position); 51 | debug("instantiateItem: virtual position: " + virtualPosition); 52 | 53 | // only expose virtual position to the inner adapter 54 | return adapter.instantiateItem(container, virtualPosition); 55 | } 56 | 57 | @Override 58 | public void destroyItem(ViewGroup container, int position, Object object) { 59 | if(getRealCount() == 0){ 60 | return; 61 | } 62 | int virtualPosition = position % getRealCount(); 63 | debug("destroyItem: real position: " + position); 64 | debug("destroyItem: virtual position: " + virtualPosition); 65 | 66 | // only expose virtual position to the inner adapter 67 | adapter.destroyItem(container, virtualPosition, object); 68 | } 69 | 70 | /* 71 | * Delegate rest of methods directly to the inner adapter. 72 | */ 73 | 74 | @Override 75 | public void finishUpdate(ViewGroup container) { 76 | adapter.finishUpdate(container); 77 | } 78 | 79 | @Override 80 | public boolean isViewFromObject(View view, Object object) { 81 | return adapter.isViewFromObject(view, object); 82 | } 83 | 84 | @Override 85 | public void restoreState(Parcelable bundle, ClassLoader classLoader) { 86 | adapter.restoreState(bundle, classLoader); 87 | } 88 | 89 | @Override 90 | public Parcelable saveState() { 91 | return adapter.saveState(); 92 | } 93 | 94 | @Override 95 | public void startUpdate(ViewGroup container) { 96 | adapter.startUpdate(container); 97 | } 98 | 99 | /* 100 | * End delegation 101 | */ 102 | 103 | private void debug(String message) { 104 | if (DEBUG) { 105 | Log.d(TAG, message); 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /library/src/main/java/com/daimajia/slider/library/Tricks/InfiniteViewPager.java: -------------------------------------------------------------------------------- 1 | package com.daimajia.slider.library.Tricks; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.PagerAdapter; 5 | import android.support.v4.view.ViewPager; 6 | import android.util.AttributeSet; 7 | 8 | /** 9 | * A {@link ViewPager} that allows pseudo-infinite paging with a wrap-around effect. Should be used with an {@link 10 | * InfinitePagerAdapter}. 11 | */ 12 | public class InfiniteViewPager extends ViewPagerEx { 13 | 14 | public InfiniteViewPager(Context context) { 15 | super(context); 16 | } 17 | 18 | public InfiniteViewPager(Context context, AttributeSet attrs) { 19 | super(context, attrs); 20 | } 21 | 22 | @Override 23 | public void setAdapter(PagerAdapter adapter) { 24 | super.setAdapter(adapter); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /library/src/main/res/drawable/indicator_corner_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /library/src/main/res/layout/indicator_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /library/src/main/res/layout/render_type_default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 14 | -------------------------------------------------------------------------------- /library/src/main/res/layout/render_type_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 14 | 24 | 29 | 30 | -------------------------------------------------------------------------------- /library/src/main/res/layout/slider_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 11 | 20 | 29 | 38 | 46 | 55 | 64 | -------------------------------------------------------------------------------- /library/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Default 16 | Accordion 17 | Background2Foreground 18 | CubeIn 19 | DepthPage 20 | Fade 21 | FlipHorizontal 22 | FlipPage 23 | Foreground2Background 24 | RotateDown 25 | RotateUp 26 | Stack 27 | Tablet 28 | ZoomIn 29 | ZoomOutSlide 30 | ZoomOut 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Slider 3 | 4 | -------------------------------------------------------------------------------- /library/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 24 | 43 | 44 | 63 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':demo', ':library' 2 | --------------------------------------------------------------------------------