diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a4da117 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# Built application files +*.apk +*.ap_ + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# Intellij +*.iml +.idea + +# Keystore files +*.jks + +# MacOS +.DS_Store diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..a4da117 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,43 @@ +# Built application files +*.apk +*.ap_ + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# Intellij +*.iml +.idea + +# Keystore files +*.jks + +# MacOS +.DS_Store diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..2e83379 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,27 @@ +apply plugin: 'com.android.application' + + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "com.wikikii.revealbanner" + minSdkVersion 15 + targetSdkVersion 27 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support.constraint:constraint-layout:1.1.2' + implementation project(":bannerlib") + +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..e7559a9 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/wikikii/revealbanner/BannerActivity.java b/app/src/main/java/com/wikikii/revealbanner/BannerActivity.java new file mode 100644 index 0000000..71857ec --- /dev/null +++ b/app/src/main/java/com/wikikii/revealbanner/BannerActivity.java @@ -0,0 +1,98 @@ +package com.wikikii.revealbanner; + +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.wikikii.bannerlib.banner.IndicatorLocation; +import com.wikikii.bannerlib.banner.LoopLayout; +import com.wikikii.bannerlib.banner.LoopStyle; +import com.wikikii.bannerlib.banner.OnDefaultImageViewLoader; +import com.wikikii.bannerlib.banner.bean.BannerInfo; +import com.wikikii.bannerlib.banner.listener.OnBannerItemClickListener; +import com.wikikii.bannerlib.banner.view.BannerBgContainer; + +import java.util.ArrayList; +import java.util.List; + +/** + * Banner指示图 + */ +public class BannerActivity extends AppCompatActivity implements OnBannerItemClickListener { + + BannerBgContainer bannerBgContainer; + LoopLayout loopLayout; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_banner); + setFullScreen(); + loopLayout = findViewById(R.id.loop_layout); + bannerBgContainer = findViewById(R.id.banner_bg_container); + loopLayout.setLoop_ms(3000);//轮播的速度(毫秒) + loopLayout.setLoop_duration(400);//滑动的速率(毫秒) + loopLayout.setScaleAnimation(true);// 设置是否需要动画 + loopLayout.setLoop_style(LoopStyle.Empty);//轮播的样式-默认empty + loopLayout.setIndicatorLocation(IndicatorLocation.Center);//指示器位置-中Center + loopLayout.initializeData(this); + // 准备数据 + ArrayList bannerInfos = new ArrayList<>(); + List bgList = new ArrayList<>(); + bannerInfos.add(new BannerInfo(R.mipmap.banner_1, "first")); + bannerInfos.add(new BannerInfo(R.mipmap.banner_2, "second")); + bgList.add(R.mipmap.banner_bg1); + bgList.add(R.mipmap.banner_bg2); + // 设置监听 + loopLayout.setOnLoadImageViewListener(new OnDefaultImageViewLoader() { + @Override + public void onLoadImageView(ImageView view, Object object) { + Glide.with(view.getContext()) + .load(object) + .into(view); + } + }); + loopLayout.setOnBannerItemClickListener(this); + if (bannerInfos.size() == 0) { + return; + } + loopLayout.setLoopData(bannerInfos); + bannerBgContainer.setBannerBackBg(this, bgList); + loopLayout.setBannerBgContainer(bannerBgContainer); + loopLayout.startLoop(); + } + + @Override + public void onBannerClick(int index, ArrayList banner) { + + } + + + void setFullScreen() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + Window window = getWindow(); + // Translucent status bar + window.setFlags( + WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, + WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = getWindow(); + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS + | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(Color.TRANSPARENT); + } + } +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_banner.xml b/app/src/main/res/layout/activity_banner.xml new file mode 100644 index 0000000..25a9bce --- /dev/null +++ b/app/src/main/res/layout/activity_banner.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..84f1951 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a2f5908 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..1b52399 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..ff10afd Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..115a4c7 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-nodpi/banner_1.png b/app/src/main/res/mipmap-nodpi/banner_1.png new file mode 100755 index 0000000..f0fa5a2 Binary files /dev/null and b/app/src/main/res/mipmap-nodpi/banner_1.png differ diff --git a/app/src/main/res/mipmap-nodpi/banner_2.png b/app/src/main/res/mipmap-nodpi/banner_2.png new file mode 100755 index 0000000..506bb7b Binary files /dev/null and b/app/src/main/res/mipmap-nodpi/banner_2.png differ diff --git a/app/src/main/res/mipmap-nodpi/banner_bg1.png b/app/src/main/res/mipmap-nodpi/banner_bg1.png new file mode 100755 index 0000000..4d2aabd Binary files /dev/null and b/app/src/main/res/mipmap-nodpi/banner_bg1.png differ diff --git a/app/src/main/res/mipmap-nodpi/banner_bg2.png b/app/src/main/res/mipmap-nodpi/banner_bg2.png new file mode 100755 index 0000000..fa6d3e7 Binary files /dev/null and b/app/src/main/res/mipmap-nodpi/banner_bg2.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..dcd3cd8 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..8ca12fe Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e19b41 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b824ebd Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..4c19a13 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..3ab3e9c --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #3F51B5 + #303F9F + #FF4081 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..219e9ff --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + RevealBanner + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..0eb88fe --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/bannerlib/.gitignore b/bannerlib/.gitignore new file mode 100644 index 0000000..a4da117 --- /dev/null +++ b/bannerlib/.gitignore @@ -0,0 +1,43 @@ +# Built application files +*.apk +*.ap_ + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# Intellij +*.iml +.idea + +# Keystore files +*.jks + +# MacOS +.DS_Store diff --git a/bannerlib/build.gradle b/bannerlib/build.gradle new file mode 100644 index 0000000..5b79c47 --- /dev/null +++ b/bannerlib/build.gradle @@ -0,0 +1,35 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 27 + + + + defaultConfig { + minSdkVersion 15 + targetSdkVersion 27 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation 'com.android.support:appcompat-v7:27.1.1' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + api "com.github.bumptech.glide:glide:4.6.1" +} diff --git a/bannerlib/proguard-rules.pro b/bannerlib/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/bannerlib/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/bannerlib/src/main/AndroidManifest.xml b/bannerlib/src/main/AndroidManifest.xml new file mode 100644 index 0000000..547cb3c --- /dev/null +++ b/bannerlib/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/IndicatorLocation.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/IndicatorLocation.java new file mode 100644 index 0000000..cb7f117 --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/IndicatorLocation.java @@ -0,0 +1,23 @@ +package com.wikikii.bannerlib.banner; + +/** + * 指示器位置 + * Left左 + * center中 + * Right右 + */ +public enum IndicatorLocation { + Left(1), + Center(0), + Right(2); + + private int value; + + IndicatorLocation(int idx) { + this.value = idx; + } + + public int getValue() { + return value; + } +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopAdapterWrapper.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopAdapterWrapper.java new file mode 100644 index 0000000..2162320 --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopAdapterWrapper.java @@ -0,0 +1,100 @@ +package com.wikikii.bannerlib.banner; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v4.view.PagerAdapter; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.wikikii.bannerlib.R; +import com.wikikii.bannerlib.banner.bean.BannerInfo; +import com.wikikii.bannerlib.banner.listener.OnBannerItemClickListener; +import com.wikikii.bannerlib.banner.listener.OnLoadImageViewListener; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + + +/** + * LoopAdapterWrapper + */ +public class LoopAdapterWrapper extends PagerAdapter { + private final Context context; + private final ArrayList bannerInfos;//banner data + private final OnBannerItemClickListener onBannerItemClickListener; + private final OnLoadImageViewListener onLoadImageViewListener; + + private Map pageMap = new HashMap<>(); //records all the pages in the ViewPager + private boolean isAnimation; + + public void setAnimation(boolean animation) { + isAnimation = animation; + } + + public LoopAdapterWrapper(Context context, ArrayList bannerInfos, OnBannerItemClickListener onBannerItemClickListener, OnLoadImageViewListener onLoadImageViewListener) { + this.context = context; + this.bannerInfos = bannerInfos; + this.onBannerItemClickListener = onBannerItemClickListener; + this.onLoadImageViewListener = onLoadImageViewListener; + } + + + @Override + public int getCount() { + return Short.MAX_VALUE; + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + container.removeView((View) object); + pageMap.remove(position); + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + final int index = position % bannerInfos.size(); + final BannerInfo bannerInfo = bannerInfos.get(index); + View child = null; + if (onLoadImageViewListener != null) { + child = onLoadImageViewListener.createImageView(context, isAnimation); + ImageView imageView = child.findViewById(R.id.iv_loop_banner); + onLoadImageViewListener.onLoadImageView(imageView, bannerInfo.data); + container.addView(child); + container.setBackgroundColor(context.getResources().getColor(android.R.color.transparent)); + child.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onBannerItemClickListener != null) + onBannerItemClickListener.onBannerClick(index, bannerInfos); + + } + }); + } else { + throw new NullPointerException("LoopViewPagerLayout onLoadImageViewListener is not initialize,Be sure to initialize the onLoadImageView"); + } + pageMap.put(position, child); + return child; + } + + + @Override + public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + super.setPrimaryItem(container, position, object); + pageMap.put(position, (View) object); + } + + //获去当前VIew的方法 + + public View getPrimaryItem(int position) { + return pageMap.get(position); + } + +} \ No newline at end of file diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopLayout.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopLayout.java new file mode 100644 index 0000000..481e49f --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopLayout.java @@ -0,0 +1,610 @@ +package com.wikikii.bannerlib.banner; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.support.annotation.DrawableRes; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.LinearInterpolator; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; + +import com.wikikii.bannerlib.R; +import com.wikikii.bannerlib.banner.bean.BannerInfo; +import com.wikikii.bannerlib.banner.listener.OnBannerItemClickListener; +import com.wikikii.bannerlib.banner.listener.OnLoadImageViewListener; +import com.wikikii.bannerlib.banner.util.L; +import com.wikikii.bannerlib.banner.util.Tools; +import com.wikikii.bannerlib.banner.view.BannerBgContainer; + +import java.lang.reflect.Field; +import java.util.ArrayList; + +/** + * 滚动视图布局 内嵌ViewPager + */ +public class LoopLayout extends RelativeLayout { + + private ViewPager loopViewPager; + private LinearLayout indicatorLayout; + private LinearLayout animIndicatorLayout; + private OnBannerItemClickListener onBannerItemClickListener = null; + private OnLoadImageViewListener onLoadImageViewListener = null; + private LoopAdapterWrapper loopAdapterWrapper; + private int totalDistance;//Little red dot all the distance to move + private int size = Tools.dip2px(getContext(), 8);//The size of the set point; + private ArrayList bannerInfos;//banner data + private ImageView animIndicator;//Little red dot on the move + private ImageView[] indicators;//Initializes the white dots + @DrawableRes + private int normalBackground = R.drawable.indicator_normal_background; + @DrawableRes + private int selectedBackground = R.drawable.indicator_selected_background; + private static final int MESSAGE_LOOP = 5; + private int loop_ms = 4000;//loop speed(ms) + private int loop_style = -1; //loop style(enum values[-1:empty,1:depth 2:zoom]) + private IndicatorLocation indicatorLocation = IndicatorLocation.Center; //Indicator Location(enum values[1:left,0:depth 2:right]) + private int loop_duration = 2000;//loop rate(ms) + private Handler handler = new Handler(Looper.getMainLooper()) { + @Override + public void dispatchMessage(Message msg) { + super.dispatchMessage(msg); + if (msg.what == MESSAGE_LOOP) { + if (loopViewPager.getCurrentItem() < Short.MAX_VALUE - 1) { + loopViewPager.setCurrentItem(loopViewPager.getCurrentItem() + 1, true); + sendEmptyMessageDelayed(MESSAGE_LOOP, getLoop_ms()); + } + } + } + }; + + + int mViewPagerIndex; + + boolean isScaleAnimation; + + public void setScaleAnimation(boolean scaleAnimation) { + isScaleAnimation = scaleAnimation; + } + + public LoopLayout(Context context) { + super(context); + } + + public LoopLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public LoopLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + + /** + * onBannerItemClickListener + * + * @param onBannerItemClickListener onBannerItemClickListener + */ + public void setOnBannerItemClickListener(OnBannerItemClickListener onBannerItemClickListener) { + this.onBannerItemClickListener = onBannerItemClickListener; + } + + /** + * OnLoadImageViewListener + * + * @param onLoadImageViewListener onLoadImageViewListener + */ + public void setOnLoadImageViewListener(OnLoadImageViewListener onLoadImageViewListener) { + this.onLoadImageViewListener = onLoadImageViewListener; + } + + private void initializeView() { + float density = getResources().getDisplayMetrics().density; + + loopViewPager = new ViewPager(getContext()); + loopViewPager.setId(R.id.loop_viewpager); + LayoutParams loop_params = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); + addView(loopViewPager, loop_params); + + // FrameLayout + FrameLayout indicatorFrameLayout = new FrameLayout(getContext()); + LayoutParams f_params = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, ((int) (20 * density))); + f_params.addRule(RelativeLayout.CENTER_HORIZONTAL); + f_params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + + switch (indicatorLocation) { + case Left: + f_params.addRule(RelativeLayout.ALIGN_PARENT_LEFT); + break; + case Right: + f_params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + break; + default: + break; + } + + f_params.setMargins(((int) (10 * density)), 0, ((int) (10 * density)), 0); + addView(indicatorFrameLayout, f_params); + + // 指标的布局 + indicatorLayout = new LinearLayout(getContext()); + FrameLayout.LayoutParams ind_params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.MATCH_PARENT); + indicatorLayout.setGravity(Gravity.CENTER); + indicatorLayout.setOrientation(LinearLayout.HORIZONTAL); + indicatorFrameLayout.addView(indicatorLayout, ind_params); + + // 动画指标布局 + animIndicatorLayout = new LinearLayout(getContext()); + FrameLayout.LayoutParams ind_params2 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); + animIndicatorLayout.setGravity(Gravity.CENTER | Gravity.START); + animIndicatorLayout.setOrientation(LinearLayout.HORIZONTAL); + indicatorFrameLayout.addView(animIndicatorLayout, ind_params2); + } + + /** + * 确保初始化数据 + * + * @param context context + */ + public void initializeData(Context context) { + initializeView(); + + L.e("LoopViewPager ---> initializeData"); + if (loop_duration > loop_ms) // 防止花屏 + loop_duration = loop_ms; + + try { + Field mField = ViewPager.class.getDeclaredField("mScroller"); + mField.setAccessible(true); + LoopScroller mScroller; + if (isScaleAnimation) { + mScroller = new LoopScroller(context, new LinearInterpolator()); + + } else { + mScroller = new LoopScroller(context); + } + + mScroller.setmDuration(loop_duration); + mField.set(loopViewPager, mScroller); + } catch (Exception e) { + e.printStackTrace(); + } + + loopViewPager.setOnTouchListener(new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_MOVE: + stopLoop(true); + break; + case MotionEvent.ACTION_UP: + startLoop(true); + break; + default: + break; + } + return false; + } + }); + } + + /** + * initialize the Data + * + * @param bannerInfos BannerInfo + */ + public void setLoopData(ArrayList bannerInfos) { + L.e("LoopViewPager ---> setLoopData"); + if (bannerInfos != null && bannerInfos.size() > 0) { + this.bannerInfos = bannerInfos; + } else { + return; + } + if (indicatorLayout.getChildCount() > 0) { + indicatorLayout.removeAllViews(); + removeView(animIndicator); + } + InitIndicator(); + InitLittleRed(); + totalDistance = 2 * size * (indicators.length - 1); + loopAdapterWrapper = new LoopAdapterWrapper(getContext(), bannerInfos, onBannerItemClickListener, onLoadImageViewListener); + loopAdapterWrapper.setAnimation(isScaleAnimation); + loopViewPager.setAdapter(loopAdapterWrapper); + loopViewPager.addOnPageChangeListener(new ViewPageChangeListener()); + int index = Short.MAX_VALUE / 2 - (Short.MAX_VALUE / 2) % bannerInfos.size(); + loopViewPager.setCurrentItem(index); + } + + private void InitIndicator() { + indicatorLayout.removeAllViews(); + indicators = new ImageView[bannerInfos.size()]; + for (int i = 0; i < indicators.length; i++) { + indicators[i] = new ImageView(getContext()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(size, size); + if (i != indicators.length - 1) { + params.setMargins(0, 0, size, 0); + } else { + params.setMargins(0, 0, 0, 0); + } + indicators[i].setLayoutParams(params); + indicators[i].setImageResource(R.drawable.icon_banner_indicator1);//设置默认的背景颜色 + indicatorLayout.addView(indicators[i]); + } + + } + + private void InitLittleRed() { + animIndicatorLayout.removeAllViews(); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(size, size); + animIndicator = new ImageView(getContext()); +// animIndicator.setGravity(Gravity.CENTER); + animIndicator.setImageResource(R.drawable.icon_banner_indicator0);//设置选中的背景颜色 + animIndicatorLayout.addView(animIndicator, params); + } + + public int getLoop_ms() { + if (loop_ms < 1500) + loop_ms = 1500; + return loop_ms; + } + + /** + * loop speed + * + * @param loop_ms (ms) + */ + public void setLoop_ms(int loop_ms) { + this.loop_ms = loop_ms; + } + + /** + * loop rate + * + * @param loop_duration (ms) + */ + public void setLoop_duration(int loop_duration) { + this.loop_duration = loop_duration; + } + + /** + * loop style + * + * @param loop_style (enum values[-1:empty,1:depth 2:zoom]) + */ + public void setLoop_style(LoopStyle loop_style) { + this.loop_style = loop_style.getValue(); + } + + /** + * 指示器的位置 + * + * @param indicatorLocation (enum values[1:left,0:depth,2:right]) + */ + public void setIndicatorLocation(IndicatorLocation indicatorLocation) { + this.indicatorLocation = indicatorLocation; + } + + /** + * startLoop + */ + public void startLoop() { + handler.removeCallbacksAndMessages(MESSAGE_LOOP); + handler.sendEmptyMessageDelayed(MESSAGE_LOOP, getLoop_ms()); + L.e("LoopViewPager ---> startLoop"); + if (loopAdapterWrapper.getPrimaryItem(loopViewPager.getCurrentItem()) != null && isScaleAnimation) { + ImageView imageView = loopAdapterWrapper.getPrimaryItem(loopViewPager.getCurrentItem()).findViewById(R.id.iv_loop_banner); + if (imageView != null) { + narrowView(imageView, loop_ms - 200); + } + } + + } + + + /** + * startLoop + */ + public void startLoop(boolean isFinger) { + handler.removeCallbacksAndMessages(MESSAGE_LOOP); + handler.sendEmptyMessageDelayed(MESSAGE_LOOP, getLoop_ms()); + L.e("LoopViewPager ---> startLoop"); + + } + + /** + * stopLoop + * 一定要在onDestroy中防止内存泄漏。 + */ + public void stopLoop() { + handler.removeMessages(MESSAGE_LOOP); + L.e("LoopViewPager ---> stopLoop"); + if (loopAdapterWrapper.getPrimaryItem(loopViewPager.getCurrentItem()) != null && isScaleAnimation) { + ImageView imageView = loopAdapterWrapper.getPrimaryItem(loopViewPager.getCurrentItem()).findViewById(R.id.iv_loop_banner); + if (imageView != null) { + enLargeView(imageView); + } + } + } + + /** + * stopLoop + * 一定要在onDestroy中防止内存泄漏。 + */ + public void stopLoop(boolean isFinger) { + handler.removeMessages(MESSAGE_LOOP); + L.e("LoopViewPager ---> stopLoop"); + + } + + /** + * LoopViewPager + * + * @return ViewPager + */ + public ViewPager getLoopViewPager() { + return loopViewPager; + } + + public int getNormalBackground() { + return normalBackground; + } + + public void setNormalBackground(@DrawableRes int normalBackground) { + this.normalBackground = normalBackground; + } + + public int getSelectedBackground() { + return selectedBackground; + } + + public void setSelectedBackground(@DrawableRes int selectedBackground) { + this.selectedBackground = selectedBackground; + } + + + BannerBgContainer bannerBgContainer; + + public void setBannerBgContainer(BannerBgContainer bannerBgContainer) { + this.bannerBgContainer = bannerBgContainer; + } + + + float reduceValue = 0.2f; + float upValue = 2.5f; + + /** + * OnPageChangeListener + */ + private class ViewPageChangeListener implements ViewPager.OnPageChangeListener { + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (loopAdapterWrapper.getCount() > 0) { + float length = ((position % bannerInfos.size()) + positionOffset) / (bannerInfos.size() - 1); + // 为了防止最后一小红点滑出去 + if (length >= 1) { + } else { + float path = length * totalDistance; + animIndicator.setTranslationX(path); + } + if (isScaleAnimation) { + ImageView imageView; + if (positionOffset == 0f) { + if (loopAdapterWrapper.getPrimaryItem(loopViewPager.getCurrentItem()) != null) { + imageView = loopAdapterWrapper.getPrimaryItem(loopViewPager.getCurrentItem()).findViewById(R.id.iv_loop_banner); + if (imageView != null) { + bigIndex = loopViewPager.getCurrentItem(); + enLargeView(imageView); + } + } + } else { + if (bigIndex != -1) { + if (loopAdapterWrapper.getPrimaryItem(bigIndex) != null) { + imageView = loopAdapterWrapper.getPrimaryItem(bigIndex).findViewById(R.id.iv_loop_banner); + if (!delayAnimationSet.isRunning()) { + delayAnimationSet.cancel(); + imageView.clearAnimation(); + } + narrowView(imageView); + } + + } + } + } + } + + if (bannerBgContainer == null) { + return; + } + if (mViewPagerIndex == position) { + if (bannerBgContainer.getBannerBgViews().size() > position % bannerBgContainer.getBannerBgViews().size() + 1) { + bannerBgContainer.getBannerBgViews().get(position % bannerBgContainer.getBannerBgViews().size() + 1).bringToFront(); + bannerBgContainer.getBannerBgViews().get(position % bannerBgContainer.getBannerBgViews().size() + 1) + .hideClipAnimation((positionOffset - reduceValue) * upValue > 1 ? 1 : (positionOffset - reduceValue) * upValue); + } else if (bannerBgContainer.getBannerBgViews().size() == position % bannerBgContainer.getBannerBgViews().size() + 1) { + bannerBgContainer.getBannerBgViews().get(0).bringToFront(); + bannerBgContainer.getBannerBgViews().get(0) + .hideClipAnimation((positionOffset - reduceValue) * upValue > 1 ? 1 : (positionOffset - reduceValue) * upValue); + } + } else { + if (position / bannerBgContainer.getBannerBgViews().size() >= 0) { + bannerBgContainer.getBannerBgViews().get(position % bannerBgContainer.getBannerBgViews().size()).bringToFront(); + bannerBgContainer.getBannerBgViews().get(position % bannerBgContainer.getBannerBgViews().size()) + .showClipAnimation(0, bannerBgContainer.getHeight() / 2, + (1 - (positionOffset + reduceValue)) * upValue > 1 ? 1 : (1 - (positionOffset + reduceValue)) * upValue); + } + } + + } + + @Override + public void onPageSelected(int position) { + int i = position % bannerInfos.size(); + if (i == 0) { + animIndicator.setTranslationX(totalDistance * 0.0f); + } else if (i == bannerInfos.size() - 1) { + animIndicator.setTranslationX(totalDistance * 1.0f); + } + mViewPagerIndex = position - 1; + } + + @Override + public void onPageScrollStateChanged(int state) { + if (state == 1) { + if (loopViewPager != null) { + mViewPagerIndex = loopViewPager.getCurrentItem(); + } + } + } + } + + + AnimatorSet animatorSetsuofang = new AnimatorSet(); + ObjectAnimator scaleX; + ObjectAnimator scaleY; + + AnimatorSet animatorSmall = new AnimatorSet(); + ObjectAnimator smallScaleX; + ObjectAnimator smallScaleY; + + + AnimatorSet delayAnimationSet = new AnimatorSet(); + ObjectAnimator delayScaleX; + ObjectAnimator delayScaleY; + int bigIndex; + + float smallScaleValue = 1.0f; + float bigScaleValue = 1.2f; + + /** + * 放大View + * + * @param view + */ + public void enLargeView(final View view) { + if (view.getScaleX() == smallScaleValue) { + scaleX = ObjectAnimator.ofFloat(view, "scaleX", smallScaleValue, bigScaleValue); + scaleY = ObjectAnimator.ofFloat(view, "scaleY", smallScaleValue, bigScaleValue); + animatorSetsuofang.setDuration(200); + animatorSetsuofang.setInterpolator(linearInterpolator); + animatorSetsuofang.play(scaleX).with(scaleY);//两个动画同时开始 + animatorSetsuofang.start(); + animatorSetsuofang.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + view.clearAnimation(); + animatorSetsuofang.removeAllListeners(); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + } + } + + /** + * 缩小View + * + * @param view + */ + public void narrowView(final View view) { + if (view != null && view.getScaleX() == bigScaleValue) { + smallScaleX = ObjectAnimator.ofFloat(view, "scaleX", bigScaleValue, smallScaleValue); + smallScaleY = ObjectAnimator.ofFloat(view, "scaleY", bigScaleValue, smallScaleValue); + animatorSmall.setDuration(100); + animatorSmall.setInterpolator(linearInterpolator); + animatorSmall.play(smallScaleX).with(smallScaleY);//两个动画同时开始 + animatorSmall.start(); + bigIndex = -1; + animatorSmall.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + view.clearAnimation(); + animatorSmall.removeAllListeners(); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + } + } + + + /** + * 缩小View + * + * @param view + */ + public void narrowView(final View view, long delayTime) { + if (view != null) { + delayScaleX = ObjectAnimator.ofFloat(view, "scaleX", bigScaleValue, smallScaleValue); + delayScaleY = ObjectAnimator.ofFloat(view, "scaleY", bigScaleValue, smallScaleValue); + delayAnimationSet.setDuration(200); + delayAnimationSet.setInterpolator(linearInterpolator); + delayAnimationSet.play(delayScaleX).with(delayScaleY);//两个动画同时开始 + delayAnimationSet.setStartDelay(delayTime); + delayAnimationSet.start(); + delayAnimationSet.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + view.clearAnimation(); + delayAnimationSet.removeAllListeners(); + } + + @Override + public void onAnimationCancel(Animator animation) { + view.clearAnimation(); + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + } + } + + + LinearInterpolator linearInterpolator = new LinearInterpolator(); + +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopScroller.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopScroller.java new file mode 100644 index 0000000..786937f --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopScroller.java @@ -0,0 +1,45 @@ +package com.wikikii.bannerlib.banner; + +import android.content.Context; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +/** + * Scroller + * 更好的用户体验 + */ +public class LoopScroller extends Scroller { + private int mDuration = 1000;//速率必须小于延迟时间loop_ms + + public LoopScroller(Context context) { + super(context); + } + + public LoopScroller(Context context, Interpolator interpolator) { + super(context, interpolator); + } + + public LoopScroller(Context context, Interpolator interpolator, boolean flywheel) { + super(context, interpolator, flywheel); + } + + + @Override + public void startScroll(int startX, int startY, int dx, int dy, int duration) { + super.startScroll(startX, startY, dx, dy, mDuration); + } + + @Override + public void startScroll(int startX, int startY, int dx, int dy) { + super.startScroll(startX, startY, dx, dy, mDuration); + } + + public void setmDuration(int time) { + mDuration = time; + } + + public int getmDuration() { + return mDuration; + } + +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopStyle.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopStyle.java new file mode 100644 index 0000000..15aeee3 --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/LoopStyle.java @@ -0,0 +1,23 @@ +package com.wikikii.bannerlib.banner; + +/** + * Loop style + * 默认empty + * 深度depth + * 缩小zoo + */ +public enum LoopStyle { + Empty(-1), + Depth(1), + Zoom(2); + private int value; + + LoopStyle(int idx) { + this.value = idx; + } + + public int getValue() { + return value; + } + +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/OnDefaultImageViewLoader.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/OnDefaultImageViewLoader.java new file mode 100644 index 0000000..51738bb --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/OnDefaultImageViewLoader.java @@ -0,0 +1,24 @@ +package com.wikikii.bannerlib.banner; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; + +import com.wikikii.bannerlib.R; +import com.wikikii.bannerlib.banner.listener.OnLoadImageViewListener; + + +public abstract class OnDefaultImageViewLoader implements OnLoadImageViewListener { + + @Override + public View createImageView(Context context, boolean isScaleAnimation) { + View view; + if (!isScaleAnimation) { + view = LayoutInflater.from(context).inflate(R.layout.item_banner, null, false); + } else { + view = LayoutInflater.from(context).inflate(R.layout.item_animation_banner, null, false); + + } + return view; + } +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/bean/BannerInfo.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/bean/BannerInfo.java new file mode 100644 index 0000000..89ecd73 --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/bean/BannerInfo.java @@ -0,0 +1,18 @@ +package com.wikikii.bannerlib.banner.bean; + +/** + * BannerInfo + * + * @author Edwin.Wu + * @version 2016/12/6 17:32 + * @since JDK1.8 + */ +public class BannerInfo { + public T data; + public String title; + + public BannerInfo(T data, String title) { + this.data = data; + this.title = title; + } +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/listener/OnBannerItemClickListener.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/listener/OnBannerItemClickListener.java new file mode 100644 index 0000000..e1d748a --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/listener/OnBannerItemClickListener.java @@ -0,0 +1,16 @@ +package com.wikikii.bannerlib.banner.listener; + + +import com.wikikii.bannerlib.banner.bean.BannerInfo; + +import java.util.ArrayList; + +public interface OnBannerItemClickListener { + /** + * banner click + * + * @param index subscript + * @param banner bean + */ + void onBannerClick(int index, ArrayList banner); +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/listener/OnLoadImageViewListener.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/listener/OnLoadImageViewListener.java new file mode 100644 index 0000000..950de85 --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/listener/OnLoadImageViewListener.java @@ -0,0 +1,28 @@ +package com.wikikii.bannerlib.banner.listener; + +import android.content.Context; +import android.view.View; +import android.widget.ImageView; + +public interface OnLoadImageViewListener { + /** + * create image + * + * @param context context + * @return image + */ + View createImageView(Context context, boolean isScaleAnimation); + + /** + * image load + * + * @param imageView ImageView + * @param parameter String 可以为一个文件路径、uri或者url + * Uri uri类型 + * File 文件 + * Integer 资源Id,R.drawable.xxx或者R.mipmap.xxx + * byte[] 类型 + * T 自定义类型 + */ + void onLoadImageView(ImageView imageView, Object parameter); +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/util/DensityUtil.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/util/DensityUtil.java new file mode 100644 index 0000000..e3a1f73 --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/util/DensityUtil.java @@ -0,0 +1,48 @@ +package com.wikikii.bannerlib.banner.util; + +import android.content.res.Resources; + +public class DensityUtil { + + public float density; + + public DensityUtil() { + density = Resources.getSystem().getDisplayMetrics().density; + } + + /** + * 根据手机的分辨率从 dp 的单位 转成为 px(像素) + * @param dpValue 虚拟像素 + * @return 像素 + */ + public static int dp2px(float dpValue) { + return (int) (0.5f + dpValue * Resources.getSystem().getDisplayMetrics().density); + } + + /** + * 根据手机的分辨率从 px(像素) 的单位 转成为 dp + * @param pxValue 像素 + * @return 虚拟像素 + */ + public static float px2dp(int pxValue) { + return (pxValue / Resources.getSystem().getDisplayMetrics().density); + } + + /** + * 根据手机的分辨率从 dp 的单位 转成为 px(像素) + * @param dpValue 虚拟像素 + * @return 像素 + */ + public int dip2px(float dpValue) { + return (int) (0.5f + dpValue * density); + } + + /** + * 根据手机的分辨率从 px(像素) 的单位 转成为 dp + * @param pxValue 像素 + * @return 虚拟像素 + */ + public float px2dip(int pxValue) { + return (pxValue / density); + } +} \ No newline at end of file diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/util/L.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/util/L.java new file mode 100644 index 0000000..9c5e23b --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/util/L.java @@ -0,0 +1,29 @@ +package com.wikikii.bannerlib.banner.util; + +import android.util.Log; + + +public class L { + public static boolean deBug = false; + public static String TAG = "LoopView"; + + public static void e(String msg) { + if (deBug) + Log.e(TAG, msg); + } + + public static void e(String TAG, String msg) { + if (deBug) + Log.e(TAG, msg); + } + + public static void e(String TAG, Throwable tr) { + if (deBug) + Log.e(TAG, "Error——", tr); + } + + public static void e(String TAG, String msg, Throwable tr) { + if (deBug) + Log.e(TAG, msg, tr); + } +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/util/Tools.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/util/Tools.java new file mode 100644 index 0000000..c348e2f --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/util/Tools.java @@ -0,0 +1,92 @@ +package com.wikikii.bannerlib.banner.util; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +/** + * 工具类 + * + * @author Edwin.Wu + * @version 2016/06/13 下午10:14 + * @since JDK1.8 + */ +public class Tools { + /** + * 根据手机的分辨率从 dp 的单位 转成为 px(像素) + * + * @param dip dip + * @return int + */ + public static int dip2px(Context context, float dip) { + float density = context.getResources().getDisplayMetrics().density; + return (int) (dip * density + 0.5f); + } + + /** + * 根据手机的分辨率从 px(像素) 的单位 转成为 dp + * + * @param px 像素 + * @return float + */ + public static float px2dip(Context context, int px) { + float density = context.getResources().getDisplayMetrics().density; + return px / density; + } + + /** + * 压缩图片 + * + * @param res 资源 + * @param resId 图片ID + * @param reqWidth 0表示获取ViewPager的宽 + * @param reqHeight 0表示获取ViewPager的高 + * @return Bitmap + */ + public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, + int reqWidth, int reqHeight) { + // 第一次解码inJustDecodeBounds = true检查尺寸 + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeResource(res, resId, options); + + // 计算inSampleSize + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + + // 解码与inSampleSize设置位图 + options.inJustDecodeBounds = false; + return BitmapFactory.decodeResource(res, resId, options); + } + + /** + * 算法 + * 假如你要求宽高200*200 + * 图片实际宽高1000*1000,除以2以后变成500*500 + * 发现比要求的还是大,就再除以2.。直到达到要求 + * + * @param options options + * @param reqWidth reqWidth + * @param reqHeight reqHeight + * @return 压缩比例 + */ + private static int calculateInSampleSize( + BitmapFactory.Options options, int reqWidth, int reqHeight) { + // 原始图像的高度和宽度 + final int height = options.outHeight; + final int width = options.outWidth; + int inSampleSize = 1; + if (height > reqHeight || width > reqWidth) { + + final int halfHeight = height / 2; + final int halfWidth = width / 2; + + // 计算最大inSampleSize值是2的幂,让两者高度和宽度大于请求的高度和宽度。 + while ((halfHeight / inSampleSize) > reqHeight + && (halfWidth / inSampleSize) > reqWidth) { + inSampleSize *= 2; + } + } + return inSampleSize; + } +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/BakedBezierInterpolator.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/BakedBezierInterpolator.java new file mode 100644 index 0000000..0ddb5af --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/BakedBezierInterpolator.java @@ -0,0 +1,52 @@ +package com.wikikii.bannerlib.banner.view; + +import android.view.animation.Interpolator; + +class BakedBezierInterpolator implements Interpolator { + + /** + * Lookup table values. + * Generated using a Bezier curve from (0,0) to (1,1) with control points: + * P0 (0,0) + * P1 (0.4, 0) + * P2 (0.2, 1.0) + * P3 (1.0, 1.0) + * + * Values sampled with x at regular intervals between 0 and 1. + */ + private static final float[] VALUES = new float[] { + 0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f, + 0.0257f, 0.0321f, 0.0392f, 0.0469f, 0.0566f, 0.0656f, 0.0768f, 0.0887f, 0.1033f, 0.1186f, + 0.1349f, 0.1519f, 0.1696f, 0.1928f, 0.2121f, 0.237f, 0.2627f, 0.2892f, 0.3109f, 0.3386f, + 0.3667f, 0.3952f, 0.4241f, 0.4474f, 0.4766f, 0.5f, 0.5234f, 0.5468f, 0.5701f, 0.5933f, + 0.6134f, 0.6333f, 0.6531f, 0.6698f, 0.6891f, 0.7054f, 0.7214f, 0.7346f, 0.7502f, 0.763f, + 0.7756f, 0.7879f, 0.8f, 0.8107f, 0.8212f, 0.8326f, 0.8415f, 0.8503f, 0.8588f, 0.8672f, + 0.8754f, 0.8833f, 0.8911f, 0.8977f, 0.9041f, 0.9113f, 0.9165f, 0.9232f, 0.9281f, 0.9328f, + 0.9382f, 0.9434f, 0.9476f, 0.9518f, 0.9557f, 0.9596f, 0.9632f, 0.9662f, 0.9695f, 0.9722f, + 0.9753f, 0.9777f, 0.9805f, 0.9826f, 0.9847f, 0.9866f, 0.9884f, 0.9901f, 0.9917f, 0.9931f, + 0.9944f, 0.9955f, 0.9964f, 0.9973f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f + }; + + private static final float STEP_SIZE = 1.0f / (VALUES.length - 1); + + @Override + public float getInterpolation(float input) { + if (input >= 1.0f) { + return 1.0f; + } + + if (input <= 0f) { + return 0f; + } + + int position = Math.min( + (int)(input * (VALUES.length - 1)), + VALUES.length - 2); + + float quantized = position * STEP_SIZE; + float difference = input - quantized; + float weight = difference / STEP_SIZE; + + return VALUES[position] + weight * (VALUES[position + 1] - VALUES[position]); + } +} \ No newline at end of file diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/BannerBgContainer.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/BannerBgContainer.java new file mode 100644 index 0000000..4a00a19 --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/BannerBgContainer.java @@ -0,0 +1,61 @@ +package com.wikikii.bannerlib.banner.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +import com.bumptech.glide.Glide; +import com.wikikii.bannerlib.banner.util.DensityUtil; +import com.wikikii.bannerlib.banner.view.BannerBgView; + +import java.util.ArrayList; +import java.util.List; + +/** + * banner 背景容器 + */ +public class BannerBgContainer extends RelativeLayout { + + private List bannerBgViews = new ArrayList<>(); + + + public BannerBgContainer(Context context) { + super(context); + } + + public BannerBgContainer(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public BannerBgContainer(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public List getBannerBgViews() { + return this.bannerBgViews; + } + + /** + * 设置 + * + * @param context + * @param bgUrlList + */ + public void setBannerBackBg(Context context, List bgUrlList) { + bannerBgViews.clear(); + this.removeAllViews(); + LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, DensityUtil.dp2px(240)); + layoutParams.leftMargin = -DensityUtil.dp2px(20); + layoutParams.rightMargin = -DensityUtil.dp2px(20); + for (Object urlImageView : bgUrlList) { + BannerBgView bannerBgView = new BannerBgView(context); + bannerBgView.setLayoutParams(layoutParams); + Glide.with(context).load(urlImageView).into(bannerBgView.getImageView()); + bannerBgViews.add(bannerBgView); + this.addView(bannerBgView); + } + bannerBgViews.get(0).bringToFront(); + } + + +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/BannerBgView.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/BannerBgView.java new file mode 100644 index 0000000..a6857f5 --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/BannerBgView.java @@ -0,0 +1,40 @@ +package com.wikikii.bannerlib.banner.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ImageView; + +/** + * banner背景图 + */ +public class BannerBgView extends RevealLayout { + + private ImageView imageView; + + public BannerBgView(Context context) { + super(context); + addImageView(context); + } + + public BannerBgView(Context context, AttributeSet attrs) { + super(context, attrs); + addImageView(context); + } + + public BannerBgView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + addImageView(context); + } + + + public void addImageView(Context context) { + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_XY); + this.addView(imageView); + } + + + public ImageView getImageView() { + return imageView; + } +} diff --git a/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/RevealLayout.java b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/RevealLayout.java new file mode 100644 index 0000000..fcf7187 --- /dev/null +++ b/bannerlib/src/main/java/com/wikikii/bannerlib/banner/view/RevealLayout.java @@ -0,0 +1,386 @@ +package com.wikikii.bannerlib.banner.view; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Path; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.Transformation; +import android.widget.FrameLayout; + + +public class RevealLayout extends FrameLayout { + + private static final int DEFAULT_DURATION = 600; + private Path mClipPath; + private int mClipCenterX, mClipCenterY = 0; + private Animation mAnimation; + + private float mClipRadius = 0; + private boolean mIsContentShown = true; + + public RevealLayout(Context context) { + this(context, null); + } + + public RevealLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public RevealLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mClipPath = new Path(); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + mClipCenterX = w / 2; + mClipCenterY = h / 2; + if (!mIsContentShown) { + mClipRadius = 0; + } else { + mClipRadius = (float) (Math.sqrt(w * w + h * h) / 2); + } + + super.onSizeChanged(w, h, oldw, oldh); + } + + public float getClipRadius() { + return mClipRadius; + } + + public void setClipRadius(float clipRadius) { + mClipRadius = clipRadius; + invalidate(); + } + + public boolean isContentShown() { + return mIsContentShown; + } + + public void setContentShown(boolean isContentShown) { + mIsContentShown = isContentShown; + if (mIsContentShown) { + mClipRadius = 0; + } else { + mClipRadius = getMaxRadius(mClipCenterX, mClipCenterY); + } + invalidate(); + } + + public void show() { + show(DEFAULT_DURATION); + } + + public void show(int duration) { + show(duration, null); + } + + public void show(int x, int y) { + show(x, y, DEFAULT_DURATION, null); + } + + public void show(@Nullable Animation.AnimationListener listener) { + show(DEFAULT_DURATION, listener); + } + + public void show(int duration, @Nullable Animation.AnimationListener listener) { + show(getWidth(), getHeight() / 2, duration, listener); + } + + public void show(int x, int y, @Nullable Animation.AnimationListener listener) { + show(x, y, DEFAULT_DURATION, listener); + } + + public void show(int x, int y, int duration) { + show(x, y, duration, null); + } + + + public void showClipAnimation(float changeValue) { + showClipAnimation(getWidth(), getHeight()/2 , changeValue); + } + + public void showClipAnimation(int x, int y, float changeValue) { + if (x < 0 || x > getWidth() || y < 0 || y > getHeight()) { + throw new RuntimeException("Center point out of range or call method when View is not initialed yet."); + } + mClipCenterX = x; + mClipCenterY = y; + final float maxRadius = getMaxRadius(x, y); + setClipRadius(changeValue * maxRadius); + } + + + public void hideClipAnimation(float changeValue) { + hideClipAnimation(getWidth(), getHeight()/2 , changeValue); + } + + public void hideClipAnimation(int x, int y, float changeValue) { + if (x < 0 || x > getWidth() || y < 0 || y > getHeight()) { + throw new RuntimeException("Center point out of range or call method when View is not initialed yet."); + } + + final float maxRadius = getMaxRadius(x, y); + if (x != mClipCenterX || y != mClipCenterY) { + mClipCenterX = x; + mClipCenterY = y; + mClipRadius = maxRadius; + } + setClipRadius(changeValue * maxRadius); + + + } + + public void show(int x, int y, int duration, @Nullable final Animation.AnimationListener listener) { + if (x < 0 || x > getWidth() || y < 0 || y > getHeight()) { + throw new RuntimeException("Center point out of range or call method when View is not initialed yet."); + } + + mClipCenterX = x; + mClipCenterY = y; + final float maxRadius = getMaxRadius(x, y); + + clearAnimation(); + + mAnimation = new Animation() { + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + setClipRadius(interpolatedTime * maxRadius); + Log.i("applayTransformation", "interpolatedTime"+ interpolatedTime); + } + }; + mAnimation.setInterpolator(new BakedBezierInterpolator()); + mAnimation.setDuration(duration); + mAnimation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationRepeat(Animation animation) { + if (listener != null) { + listener.onAnimationRepeat(animation); + } + } + + @Override + public void onAnimationStart(Animation animation) { + mIsContentShown = true; + if (listener != null) { + listener.onAnimationStart(animation); + } + } + + @Override + public void onAnimationEnd(Animation animation) { + if (listener != null) { + listener.onAnimationEnd(animation); + } + } + }); + startAnimation(mAnimation); + } + + public void hide() { + hide(DEFAULT_DURATION); + } + + public void hide(int duration) { + hide(getWidth(), getHeight() / 2, duration, null); + } + + public void hide(int x, int y) { + hide(x, y, DEFAULT_DURATION, null); + } + + public void hide(@Nullable Animation.AnimationListener listener) { + hide(DEFAULT_DURATION, listener); + } + + public void hide(int duration, @Nullable Animation.AnimationListener listener) { + hide(getWidth() / 2, getHeight() / 2, duration, listener); + } + + public void hide(int x, int y, @Nullable Animation.AnimationListener listener) { + hide(x, y, DEFAULT_DURATION, listener); + } + + public void hide(int x, int y, int duration) { + hide(x, y, duration, null); + } + + public void hide(int x, int y, int duration, @Nullable final Animation.AnimationListener listener) { + if (x < 0 || x > getWidth() || y < 0 || y > getHeight()) { + throw new RuntimeException("Center point out of range or call method when View is not initialed yet."); + } + + final float maxRadius = getMaxRadius(x, y); + if (x != mClipCenterX || y != mClipCenterY) { + mClipCenterX = x; + mClipCenterY = y; + mClipRadius = maxRadius; + } + + clearAnimation(); + + mAnimation = new Animation() { + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + setClipRadius(maxRadius * (1 - interpolatedTime)); + } + }; + mAnimation.setInterpolator(new BakedBezierInterpolator()); + mAnimation.setDuration(duration); + mAnimation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + mIsContentShown = false; + if (listener != null) { + listener.onAnimationStart(animation); + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + if (listener != null) { + listener.onAnimationRepeat(animation); + } + } + + @Override + public void onAnimationEnd(Animation animation) { + if (listener != null) { + listener.onAnimationEnd(animation); + } + } + }); + startAnimation(mAnimation); + } + + public void next() { + next(DEFAULT_DURATION); + } + + public void next(int duration) { + next(getWidth() / 2, getHeight() / 2, duration, null); + } + + public void next(int x, int y) { + next(x, y, DEFAULT_DURATION, null); + } + + public void next(@Nullable Animation.AnimationListener listener) { + next(DEFAULT_DURATION, listener); + } + + public void next(int duration, @Nullable Animation.AnimationListener listener) { + next(getWidth() / 2, getHeight() / 2, duration, listener); + } + + public void next(int x, int y, @Nullable Animation.AnimationListener listener) { + next(x, y, DEFAULT_DURATION, listener); + } + + public void next(int x, int y, int duration) { + next(x, y, duration, null); + } + + public void next(int x, int y, int duration, @Nullable Animation.AnimationListener listener) { + final int childCount = getChildCount(); + if (childCount > 1) { + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (i == 0) { + bringChildToFront(child); + } + } + show(x, y, duration, listener); + } + } + + private float getMaxRadius(int x, int y) { + int h = Math.max(x, getWidth() - x); + int v = Math.max(y, getHeight() - y); + return (float) Math.sqrt(h * h + v * v); + } + + @Override + protected boolean drawChild(@NonNull Canvas canvas, @NonNull View child, long drawingTime) { + if (indexOfChild(child) == getChildCount() - 1) { + boolean result; + mClipPath.reset(); + mClipPath.addCircle(mClipCenterX, mClipCenterY, mClipRadius, Path.Direction.CW); + +// Log.d("RevealLayout", "ClipRadius: " + mClipRadius); + canvas.save(); + canvas.clipPath(mClipPath); + result = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return result; + } else { + return super.drawChild(canvas, child, drawingTime); + } + } + + @Override + protected Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.isContentShown = mIsContentShown; + return ss; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + + setContentShown(ss.isContentShown); + } + + public static class SavedState extends BaseSavedState { + + boolean isContentShown; + + SavedState(Parcelable superState) { + super(superState); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt(isContentShown ? 1 : 0); + } + + @SuppressWarnings("hiding") + public static final Creator CREATOR + = new Creator() { + public RevealLayout.SavedState createFromParcel(Parcel in) { + return new RevealLayout.SavedState(in); + } + + public RevealLayout.SavedState[] newArray(int size) { + return new RevealLayout.SavedState[size]; + } + }; + + private SavedState(Parcel in) { + super(in); + isContentShown = in.readInt() == 1; + } + } +} \ No newline at end of file diff --git a/bannerlib/src/main/res/drawable/icon_banner_indicator0.png b/bannerlib/src/main/res/drawable/icon_banner_indicator0.png new file mode 100755 index 0000000..60a94b3 Binary files /dev/null and b/bannerlib/src/main/res/drawable/icon_banner_indicator0.png differ diff --git a/bannerlib/src/main/res/drawable/icon_banner_indicator1.png b/bannerlib/src/main/res/drawable/icon_banner_indicator1.png new file mode 100755 index 0000000..7c34706 Binary files /dev/null and b/bannerlib/src/main/res/drawable/icon_banner_indicator1.png differ diff --git a/bannerlib/src/main/res/drawable/indicator_normal_background.xml b/bannerlib/src/main/res/drawable/indicator_normal_background.xml new file mode 100644 index 0000000..4895a93 --- /dev/null +++ b/bannerlib/src/main/res/drawable/indicator_normal_background.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/bannerlib/src/main/res/drawable/indicator_selected_background.xml b/bannerlib/src/main/res/drawable/indicator_selected_background.xml new file mode 100644 index 0000000..cecfd1b --- /dev/null +++ b/bannerlib/src/main/res/drawable/indicator_selected_background.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/bannerlib/src/main/res/layout/item_animation_banner.xml b/bannerlib/src/main/res/layout/item_animation_banner.xml new file mode 100644 index 0000000..9d83222 --- /dev/null +++ b/bannerlib/src/main/res/layout/item_animation_banner.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/bannerlib/src/main/res/layout/item_banner.xml b/bannerlib/src/main/res/layout/item_banner.xml new file mode 100644 index 0000000..9578167 --- /dev/null +++ b/bannerlib/src/main/res/layout/item_banner.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/bannerlib/src/main/res/values/ids.xml b/bannerlib/src/main/res/values/ids.xml new file mode 100644 index 0000000..48c6aae --- /dev/null +++ b/bannerlib/src/main/res/values/ids.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/bannerlib/src/main/res/values/strings.xml b/bannerlib/src/main/res/values/strings.xml new file mode 100644 index 0000000..ec03134 --- /dev/null +++ b/bannerlib/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + bannerlib + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..a443fad --- /dev/null +++ b/build.gradle @@ -0,0 +1,25 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.1.3' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..743d692 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,13 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7a3265e Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..6ef87fe --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Jul 31 18:07:11 CST 2018 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..6d626bd --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':app', ':bannerlib'