diff --git a/.gitignore b/.gitignore index 874df11..8927af0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,35 +1,19 @@ +*.iml .gradle /local.properties -/.idea/workspace.xml +/.idea/caches /.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml .DS_Store /build /captures - - -# Files for the Dalvik VM -*.dex - -# Java class files -*.class - -# Generated files -bin/ -gen/ - -# Gradle files -.gradle/ -build/ -/*/build/ - -# Local configuration file (sdk path, etc) +.externalNativeBuild +.cxx local.properties - -# Proguard folder generated by Eclipse -proguard/ - -# Log Files -*.log - -# Svn -.svn/ \ No newline at end of file +/.idea/ +/gradle/wrapper/ +/gradlew.bat +/gradlew diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index d6179d4..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -CursorWheelLayout \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 96cc43e..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 6e1114a..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index a846f05..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - - - - - - - - - - - - - Android - - - Android > Lint > Correctness - - - Android > Lint > Correctness > Messages - - - Android > Lint > Internationalization - - - Android > Lint > Security - - - Android > Lint > Usability - - - Android > Lint > Usability > Icons - - - C/C++ - - - Class structureJava - - - Control flow issuesJava - - - Error handlingJava - - - General - - - Groovy - - - HTML - - - ImportsJava - - - Internationalization issues - - - Internationalization issuesJava - - - J2ME issuesJava - - - JSON - - - Java - - - Javadoc issuesJava - - - Manifest - - - OtherGroovy - - - Portability issuesJava - - - Potentially confusing code constructsGroovy - - - Probable bugsJava - - - Properties Files - - - Properties FilesJava - - - RELAX NG - - - Resource management issuesJava - - - TestNGJava - - - Threading issuesJava - - - Unused codeC/C++ - - - Validity issuesGroovy - - - XML - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index b9eeaab..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/CursorWheelLayout.iml b/CursorWheelLayout.iml index c5ca878..47d5882 100644 --- a/CursorWheelLayout.iml +++ b/CursorWheelLayout.iml @@ -8,10 +8,11 @@ - + + @@ -221,4 +222,8 @@ + + \ No newline at end of file diff --git a/app/app.iml b/app/app.iml index fa18371..e0955a4 100644 --- a/app/app.iml +++ b/app/app.iml @@ -1,330 +1,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 6d015a5..c0371f2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,28 +1,53 @@ -apply plugin: 'com.android.application' +plugins { + id 'com.android.application' + id 'kotlin-android' + id 'kotlin-kapt' +} android { - compileSdkVersion 23 - buildToolsVersion "23.0.3" + compileSdkVersion 30 + buildToolsVersion "30.0.2" defaultConfig { - applicationId "github.hellocsl.cursorwheellayout" + applicationId "github.hellocsl.cursorwheel" minSdkVersion 14 - targetSdkVersion 23 - versionCode 1 - versionName "1.0" + targetSdkVersion 30 + versionCode 3 + versionName "2.0.01" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + buildTypes { release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + buildFeatures { + dataBinding true + } } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - testCompile 'junit:junit:4.12' - compile 'com.android.support:appcompat-v7:23.2.1' - compile project(':library') - compile 'com.jakewharton:butterknife:7.0.1' -} + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation project(':library') + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.core:core-ktx:1.3.2' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' + + testImplementation 'junit:junit:4.13.1' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' +} \ No newline at end of file diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/MainActivity.java b/app/src/main/java/github/hellocsl/cursorwheellayout/MainActivity.java deleted file mode 100644 index f12c058..0000000 --- a/app/src/main/java/github/hellocsl/cursorwheellayout/MainActivity.java +++ /dev/null @@ -1,91 +0,0 @@ -package github.hellocsl.cursorwheellayout; - -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.view.Gravity; -import android.view.View; -import android.widget.Button; -import android.widget.Toast; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import butterknife.Bind; -import butterknife.ButterKnife; -import butterknife.OnClick; -import github.hellocsl.cursorwheel.CursorWheelLayout; -import github.hellocsl.cursorwheellayout.adapter.SimpleImageAdapter; -import github.hellocsl.cursorwheellayout.adapter.SimpleTextAdapter; -import github.hellocsl.cursorwheellayout.data.ImageData; -import github.hellocsl.cursorwheellayout.data.MenuItemData; -import github.hellocsl.cursorwheellayout.widget.SimpleTextCursorWheelLayout; - -public class MainActivity extends AppCompatActivity implements CursorWheelLayout.OnMenuSelectedListener { - - @Bind(R.id.test_circle_menu_left) - SimpleTextCursorWheelLayout mTestCircleMenuLeft; - @Bind(R.id.test_circle_menu_right) - SimpleTextCursorWheelLayout mTestCircleMenuRight; - @Bind(R.id.main_button_random_selected) - Button mMainButtonRadonSelected; - Random mRandom = new Random(); - @Bind(R.id.test_circle_menu_top) - CursorWheelLayout mTestCircleMenuTop; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - ButterKnife.bind(this); - initData(); - } - - private void initData() { - String[] res = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "OFF"}; - List menuItemDatas = new ArrayList(); - for (int i = 0; i < res.length; i++) { - menuItemDatas.add(new MenuItemData(res[i])); - } - SimpleTextAdapter simpleTextAdapter = new SimpleTextAdapter(this, menuItemDatas, Gravity.TOP | Gravity.CENTER_HORIZONTAL); - mTestCircleMenuLeft.setAdapter(simpleTextAdapter); - mTestCircleMenuLeft.setOnMenuSelectedListener(this); - SimpleTextAdapter simpleTextAdapter2 = new SimpleTextAdapter(this, menuItemDatas, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL); - mTestCircleMenuRight.setAdapter(simpleTextAdapter2); - mTestCircleMenuRight.setOnMenuSelectedListener(this); - List imageDatas = new ArrayList(); - imageDatas.add(new ImageData(R.drawable.ic_bank_bc, "0")); - imageDatas.add(new ImageData(R.drawable.ic_bank_china, "1")); - imageDatas.add(new ImageData(R.drawable.ic_bank_guangda, "2")); - imageDatas.add(new ImageData(R.drawable.ic_bank_guangfa, "3")); - imageDatas.add(new ImageData(R.drawable.ic_bank_jianshe, "4")); - imageDatas.add(new ImageData(R.drawable.ic_bank_jiaotong, "5")); - SimpleImageAdapter simpleImageAdapter = new SimpleImageAdapter(this, imageDatas); - mTestCircleMenuTop.setAdapter(simpleImageAdapter); - mTestCircleMenuTop.setOnMenuSelectedListener(new CursorWheelLayout.OnMenuSelectedListener() { - @Override - public void onItemSelected(CursorWheelLayout parent, View view, int pos) { - Toast.makeText(MainActivity.this, "Top Menu selected position:" + pos, Toast.LENGTH_SHORT).show(); - } - }); - mTestCircleMenuTop.setOnMenuItemClickListener(new CursorWheelLayout.OnMenuItemClickListener() { - @Override - public void onItemClick(View view, int pos) { - Toast.makeText(MainActivity.this, "Top Menu click position:" + pos, Toast.LENGTH_SHORT).show(); - - } - }); - } - - @Override - public void onItemSelected(CursorWheelLayout p, View view, int pos) { - } - - @OnClick(R.id.main_button_random_selected) - void onRandomClick() { - int index = mRandom.nextInt(10); - mTestCircleMenuLeft.setSelection(index); - mTestCircleMenuRight.setSelection(index, false); - mMainButtonRadonSelected.setText("Random Selected:" + index); - } -} diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/MainActivity.kt b/app/src/main/java/github/hellocsl/cursorwheellayout/MainActivity.kt new file mode 100644 index 0000000..ff58290 --- /dev/null +++ b/app/src/main/java/github/hellocsl/cursorwheellayout/MainActivity.kt @@ -0,0 +1,87 @@ +package github.hellocsl.cursorwheellayout + +import android.os.Bundle +import android.view.Gravity +import android.view.View +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.databinding.DataBindingUtil +import github.hellocsl.cursorwheel.CursorWheelLayout +import github.hellocsl.cursorwheel.CursorWheelLayout.OnMenuSelectedListener +import github.hellocsl.cursorwheellayout.adapter.SimpleImageAdapter +import github.hellocsl.cursorwheellayout.adapter.SimpleTextAdapter +import github.hellocsl.cursorwheellayout.data.ImageData +import github.hellocsl.cursorwheellayout.data.MenuItemData +import github.hellocsl.cursorwheellayout.databinding.ActivityMainBinding +import java.util.* + +class MainActivity : AppCompatActivity(), OnMenuSelectedListener { + private lateinit var viewBinding: ActivityMainBinding + + private var mRandom = Random() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + viewBinding = DataBindingUtil.setContentView(this, R.layout.activity_main) + initData() + } + + private fun initData() { + val res = arrayOf("0", "1", "2", "3", "4", "5", "6", "7", "8", "OFF") + val menuItemDatas: MutableList = ArrayList() + for (i in res.indices) { + menuItemDatas.add(MenuItemData(res[i])) + } + val simpleTextAdapter = + SimpleTextAdapter(this, menuItemDatas, Gravity.TOP or Gravity.CENTER_HORIZONTAL) + viewBinding.testCircleMenuLeft.setAdapter(simpleTextAdapter) + viewBinding.testCircleMenuLeft.setOnMenuSelectedListener(this) + + val simpleTextAdapter2 = + SimpleTextAdapter(this, menuItemDatas, Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL) + viewBinding.testCircleMenuRight.setAdapter(simpleTextAdapter2) + viewBinding.testCircleMenuRight.setOnMenuSelectedListener(this) + val imageDatas: MutableList = ArrayList() + imageDatas.add(ImageData(R.drawable.ic_bank_bc, "0")) + imageDatas.add(ImageData(R.drawable.ic_bank_china, "1")) + imageDatas.add(ImageData(R.drawable.ic_bank_guangda, "2")) + imageDatas.add(ImageData(R.drawable.ic_bank_guangfa, "3")) + imageDatas.add(ImageData(R.drawable.ic_bank_jianshe, "4")) + imageDatas.add(ImageData(R.drawable.ic_bank_jiaotong, "5")) + val simpleImageAdapter = SimpleImageAdapter(this, imageDatas) + viewBinding.testCircleMenuTop.setAdapter(simpleImageAdapter) + viewBinding.testCircleMenuTop.setOnMenuSelectedListener(object : OnMenuSelectedListener { + override fun onItemSelected(parent: CursorWheelLayout, view: View?, pos: Int) { + Toast.makeText( + this@MainActivity, + "Top Menu selected position:$pos", + Toast.LENGTH_SHORT + ).show() + } + }) + + viewBinding.testCircleMenuTop.setOnMenuItemClickListener(object : + CursorWheelLayout.OnMenuItemClickListener { + override fun onItemClick(view: View?, pos: Int) { + Toast.makeText( + this@MainActivity, + "Top Menu click position:$pos", + Toast.LENGTH_SHORT + ).show() + } + }) + + viewBinding.mainButtonRandomSelected.setOnClickListener { + onRandomClick() + } + } + + override fun onItemSelected(p: CursorWheelLayout, view: View?, pos: Int) {} + + private fun onRandomClick() { + val index = mRandom.nextInt(10) + viewBinding.testCircleMenuLeft.setSelection(index) + viewBinding.testCircleMenuRight.setSelection(index, false) + viewBinding.mainButtonRandomSelected.text = "Random Selected:$index" + } +} \ No newline at end of file diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleImageAdapter.java b/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleImageAdapter.java deleted file mode 100644 index 2e8bf6f..0000000 --- a/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleImageAdapter.java +++ /dev/null @@ -1,47 +0,0 @@ -package github.hellocsl.cursorwheellayout.adapter; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; - -import java.util.List; - -import github.hellocsl.cursorwheel.CursorWheelLayout; -import github.hellocsl.cursorwheellayout.R; -import github.hellocsl.cursorwheellayout.data.ImageData; - -/** - * Created by chensuilun on 16/4/24. - */ -public class SimpleImageAdapter extends CursorWheelLayout.CycleWheelAdapter { - private List mMenuItemDatas; - private LayoutInflater mLayoutInflater; - private Context mContext; - - public SimpleImageAdapter(Context context, List menuItemDatas) { - mContext = context; - mLayoutInflater = LayoutInflater.from(context); - mMenuItemDatas = menuItemDatas; - } - - @Override - public int getCount() { - return mMenuItemDatas == null ? 0 : mMenuItemDatas.size(); - } - - @Override - public View getView(View parent, int position) { - ImageData item = getItem(position); - View root = mLayoutInflater.inflate(R.layout.wheel_image_item, null, false); - ImageView imgView = (ImageView) root.findViewById(R.id.wheel_menu_item_iv); - imgView.setImageResource(item.mImageRes); - return root; - } - - @Override - public ImageData getItem(int position) { - return mMenuItemDatas.get(position); - } - -} diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleImageAdapter.kt b/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleImageAdapter.kt new file mode 100644 index 0000000..43779d9 --- /dev/null +++ b/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleImageAdapter.kt @@ -0,0 +1,34 @@ +package github.hellocsl.cursorwheellayout.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.widget.ImageView +import github.hellocsl.cursorwheel.CursorWheelLayout.CycleWheelAdapter +import github.hellocsl.cursorwheellayout.R +import github.hellocsl.cursorwheellayout.data.ImageData + +/** + * Created by chensuilun on 16/4/24. + */ +class SimpleImageAdapter( + mContext: Context, private val mMenuItemDatas: List +) : CycleWheelAdapter() { + + private val mLayoutInflater: LayoutInflater = LayoutInflater.from(mContext) + override fun getCount(): Int { + return mMenuItemDatas.size + } + + override fun getView(parent: View?, position: Int): View { + val (mImageRes) = getItem(position) + val root = mLayoutInflater.inflate(R.layout.wheel_image_item, null, false) + val imgView = root.findViewById(R.id.wheel_menu_item_iv) + imgView.setImageResource(mImageRes) + return root + } + + override fun getItem(position: Int): ImageData { + return mMenuItemDatas[position] + } +} \ No newline at end of file diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleTextAdapter.java b/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleTextAdapter.java deleted file mode 100644 index 9048000..0000000 --- a/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleTextAdapter.java +++ /dev/null @@ -1,66 +0,0 @@ -package github.hellocsl.cursorwheellayout.adapter; - -import android.content.Context; -import android.support.v4.app.ActivityCompat; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.TextView; - -import java.util.List; - -import github.hellocsl.cursorwheel.CursorWheelLayout; -import github.hellocsl.cursorwheellayout.R; -import github.hellocsl.cursorwheellayout.data.MenuItemData; - -/** - * Created by chensuilun on 16/4/24. - */ -public class SimpleTextAdapter extends CursorWheelLayout.CycleWheelAdapter { - private List mMenuItemDatas; - private LayoutInflater mLayoutInflater; - private Context mContext; - public static final int INDEX_SPEC = 9; - private int mGravity; - - public SimpleTextAdapter(Context context, List menuItemDatas) { - this(context, menuItemDatas, Gravity.CENTER); - } - - public SimpleTextAdapter(Context context, List menuItemDatas, int gravity) { - mContext = context; - mLayoutInflater = LayoutInflater.from(context); - mMenuItemDatas = menuItemDatas; - mGravity = gravity; - } - - @Override - public int getCount() { - return mMenuItemDatas == null ? 0 : mMenuItemDatas.size(); - } - - @Override - public View getView(View parent, int position) { - MenuItemData item = getItem(position); - View root = mLayoutInflater.inflate(R.layout.wheel_menu_item, null, false); - TextView textView = (TextView) root.findViewById(R.id.wheel_menu_item_tv); - textView.setVisibility(View.VISIBLE); - textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); - textView.setText(item.mTitle); - if (textView.getLayoutParams() instanceof FrameLayout.LayoutParams) { - ((FrameLayout.LayoutParams) textView.getLayoutParams()).gravity = mGravity; - } - if (position == INDEX_SPEC) { - textView.setTextColor(ActivityCompat.getColor(mContext, R.color.red)); - } - return root; - } - - @Override - public MenuItemData getItem(int position) { - return mMenuItemDatas.get(position); - } - -} diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleTextAdapter.kt b/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleTextAdapter.kt new file mode 100644 index 0000000..6ee3951 --- /dev/null +++ b/app/src/main/java/github/hellocsl/cursorwheellayout/adapter/SimpleTextAdapter.kt @@ -0,0 +1,53 @@ +package github.hellocsl.cursorwheellayout.adapter + +import android.content.Context +import android.util.TypedValue +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.widget.FrameLayout +import android.widget.TextView +import androidx.core.app.ActivityCompat +import github.hellocsl.cursorwheel.CursorWheelLayout.CycleWheelAdapter +import github.hellocsl.cursorwheellayout.R +import github.hellocsl.cursorwheellayout.data.MenuItemData + +/** + * Created by chensuilun on 16/4/24. + */ +class SimpleTextAdapter constructor( + private val mContext: Context, + val mMenuItemDatas: List, + val mGravity: Int = Gravity.CENTER +) : CycleWheelAdapter() { + + private val mLayoutInflater: LayoutInflater = LayoutInflater.from(mContext) + + override fun getCount(): Int { + return mMenuItemDatas.size + } + + override fun getView(parent: View?, position: Int): View { + val (mTitle) = getItem(position) + val root = mLayoutInflater.inflate(R.layout.wheel_menu_item, null, false) + val textView = root.findViewById(R.id.wheel_menu_item_tv) as TextView + textView.visibility = View.VISIBLE + textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f) + textView.text = mTitle + if (textView.layoutParams is FrameLayout.LayoutParams) { + (textView.layoutParams as FrameLayout.LayoutParams).gravity = mGravity + } + if (position == INDEX_SPEC) { + textView.setTextColor(ActivityCompat.getColor(mContext, R.color.red)) + } + return root + } + + override fun getItem(position: Int): MenuItemData { + return mMenuItemDatas[position] + } + + companion object { + const val INDEX_SPEC = 9 + } +} \ No newline at end of file diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/data/ImageData.java b/app/src/main/java/github/hellocsl/cursorwheellayout/data/ImageData.java deleted file mode 100644 index 5a9a29d..0000000 --- a/app/src/main/java/github/hellocsl/cursorwheellayout/data/ImageData.java +++ /dev/null @@ -1,14 +0,0 @@ -package github.hellocsl.cursorwheellayout.data; - -/** - * Created by chensuilun on 16/4/24. - */ -public class ImageData { - public int mImageRes; - public String mDesc; - - public ImageData(int imageRes, String desc) { - mImageRes = imageRes; - mDesc = desc; - } -} diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/data/ImageData.kt b/app/src/main/java/github/hellocsl/cursorwheellayout/data/ImageData.kt new file mode 100644 index 0000000..3685b22 --- /dev/null +++ b/app/src/main/java/github/hellocsl/cursorwheellayout/data/ImageData.kt @@ -0,0 +1,6 @@ +package github.hellocsl.cursorwheellayout.data + +/** + * Created by chensuilun on 16/4/24. + */ +data class ImageData(val mImageRes: Int, val mDesc: String) \ No newline at end of file diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/data/MenuItemData.java b/app/src/main/java/github/hellocsl/cursorwheellayout/data/MenuItemData.java deleted file mode 100644 index d032957..0000000 --- a/app/src/main/java/github/hellocsl/cursorwheellayout/data/MenuItemData.java +++ /dev/null @@ -1,15 +0,0 @@ -package github.hellocsl.cursorwheellayout.data; - -/** - * describe the menu item - *

- * Created by chensuilun on 16-4-19. - */ -public class MenuItemData { - - public String mTitle; - - public MenuItemData(String title) { - mTitle = title; - } -} diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/data/MenuItemData.kt b/app/src/main/java/github/hellocsl/cursorwheellayout/data/MenuItemData.kt new file mode 100644 index 0000000..406cee6 --- /dev/null +++ b/app/src/main/java/github/hellocsl/cursorwheellayout/data/MenuItemData.kt @@ -0,0 +1,9 @@ +package github.hellocsl.cursorwheellayout.data + +/** + * describe the menu item + * + * + * Created by chensuilun on 16-4-19. + */ +data class MenuItemData(val mTitle: String) \ No newline at end of file diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SimpleTextCursorWheelLayout.java b/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SimpleTextCursorWheelLayout.java deleted file mode 100644 index 5484c64..0000000 --- a/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SimpleTextCursorWheelLayout.java +++ /dev/null @@ -1,45 +0,0 @@ -package github.hellocsl.cursorwheellayout.widget; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; - -import github.hellocsl.cursorwheel.CursorWheelLayout; -import github.hellocsl.cursorwheellayout.R; - -/** - * - * Created by chensuilun on 16-4-19. - */ -public class SimpleTextCursorWheelLayout extends CursorWheelLayout { - public static final int MENU_COUNT = 10; - public static final int INDEX_SPEC = 9; - - public SimpleTextCursorWheelLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - - @Override - protected void onInnerItemSelected(View v) { - super.onInnerItemSelected(v); - if (v == null) { - return; - } - View tv = v.findViewById(R.id.wheel_menu_item_tv); - tv.animate().scaleX(2).scaleY(2); - } - - - @Override - protected void onInnerItemUnselected(View v) { - super.onInnerItemUnselected(v); - if (v == null) { - return; - } - View tv = v.findViewById(R.id.wheel_menu_item_tv); - tv.animate().scaleX(1).scaleY(1); - } - - -} diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SimpleTextCursorWheelLayout.kt b/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SimpleTextCursorWheelLayout.kt new file mode 100644 index 0000000..3a72da2 --- /dev/null +++ b/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SimpleTextCursorWheelLayout.kt @@ -0,0 +1,30 @@ +package github.hellocsl.cursorwheellayout.widget + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import github.hellocsl.cursorwheel.CursorWheelLayout +import github.hellocsl.cursorwheellayout.R + +/** + * + * Created by chensuilun on 16-4-19. + */ +class SimpleTextCursorWheelLayout(context: Context, attrs: AttributeSet?) : CursorWheelLayout(context, attrs) { + override fun onInnerItemSelected(v: View?) { + super.onInnerItemSelected(v) + val tv = v?.findViewById(R.id.wheel_menu_item_tv) + tv?.animate()?.scaleX(2f)?.scaleY(2f) + } + + override fun onInnerItemUnselected(v: View?) { + super.onInnerItemUnselected(v) + val tv = v?.findViewById(R.id.wheel_menu_item_tv) + tv?.animate()?.scaleX(1f)?.scaleY(1f) + } + + companion object { + const val MENU_COUNT = 10 + const val INDEX_SPEC = 9 + } +} \ No newline at end of file diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SwitchButton.java b/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SwitchButton.java deleted file mode 100644 index bcb4a25..0000000 --- a/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SwitchButton.java +++ /dev/null @@ -1,460 +0,0 @@ -package github.hellocsl.cursorwheellayout.widget; - -import android.animation.ArgbEvaluator; -import android.animation.ObjectAnimator; -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.ColorInt; -import android.util.AttributeSet; -import android.view.SoundEffectConstants; -import android.view.View; - -import github.hellocsl.cursorwheellayout.R; - - -/** - *

- * Created by chensuilun on 16-4-13. - */ -public class SwitchButton extends View { - private static final String TAG = "SwitchButton"; - private static final int PROGRESS_MIN = 0; - private static final int PROGRESS_MAX = 100; - private static final int DEFAULT_BOARD_WIDTH = 4; // dp - private static final int DEFAULT_BOARD_COLOR = 0xFF3c4952; - private static final int DEFAULT_UNCHECK_REVEAL_COLOR = 0xFF3c4952; - //DRAWABLE GRAVITY - public static final int DRAWABLE_GRAVITY_LEFT = 0; - public static final int DRAWABLE_GRAVITY_RIGHT = 1; - public static final int DEFAULT_DRAWABLE_GRAVITY = -1; - - // private static final int DEFAULT_UNCHECK_REVEAL_COLOR = 0X1D1F22; - private static final int DEFAULT_CHECK_REVEAL_COLOR = 0xFFFFC52A; - private static final int DEFAULT_DISABLE_COVER_COLOR = 0x4cffffff; - private static final int DEFAULT_CHECK_DRAWABLE_ID = R.mipmap.ic_launcher; - private static final int DEFAULT_UNCHECK_DRAWABLE_ID = R.mipmap.ic_launcher; - - private static final int DEFAULT_SIZE = 126; //dp - - private int mDrawableGravity = DEFAULT_DRAWABLE_GRAVITY; - /** - * 画边界 - */ - private Paint mBroadPaint; - - /** - * 覆盖层 - */ - private Paint mCoverPaint; - /** - * 画扩散进度 - */ - private Paint mRevealBgPaint; - /** - * 边框颜色 - */ - private - @ColorInt - int mBoardColor = DEFAULT_BOARD_COLOR; - - - /** - * 边框厚度 - */ - private int mBoardWidth; - /** - * 选中的时候的颜色 - */ - private int mCheckRevealColor = DEFAULT_BOARD_COLOR; - - /** - * 未选中时候的颜色 - */ - private int mUnCheckRevealColor = DEFAULT_UNCHECK_REVEAL_COLOR; - - /** - * 用于动画 0-100 选中的时候; - */ - private int mProgress; - - private boolean mChecked; - - private boolean mBroadcasting; - - private OnCheckedChangeListener mOnCheckedChangeListener; - /** - * 未选中的时候的资源ID - */ - private Drawable mUncheckDrawable; - /** - * 未选中的时候的资源ID - */ - private Drawable mCheckedDrawable; - - private ArgbEvaluator mArgbEvaluator; - private float mFraction; - private ObjectAnimator mCheckAnim; - private boolean mAttachedToWindow; - - public SwitchButton(Context context) { - this(context, null); - } - - public SwitchButton(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public SwitchButton(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs); - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public SwitchButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(context, attrs); - } - - private void init(Context context, AttributeSet attrs) { - setClickable(true); - mArgbEvaluator = new ArgbEvaluator(); - final float density = context.getResources().getDisplayMetrics().density; - mBoardWidth = (int) (DEFAULT_BOARD_WIDTH * density + 0.5); - //TODO 更多自定义属性的获取,这里hardcode先,以后有需要在提取出来 - if (attrs != null) { - TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SwitchButton); - int checkRes = ta.getResourceId(R.styleable.SwitchButton_checkSrc, DEFAULT_CHECK_DRAWABLE_ID); - mCheckedDrawable = context.getResources().getDrawable(checkRes); - int uncheckRes = ta.getResourceId(R.styleable.SwitchButton_uncheckSrc, DEFAULT_UNCHECK_DRAWABLE_ID); - mUncheckDrawable = context.getResources().getDrawable(uncheckRes); - mBoardWidth = ta.getDimensionPixelOffset(R.styleable.SwitchButton_boardWidth, mBoardWidth); - mCheckRevealColor = ta.getColor(R.styleable.SwitchButton_checkRevealColor, DEFAULT_CHECK_REVEAL_COLOR); - mUnCheckRevealColor = ta.getColor(R.styleable.SwitchButton_uncheckRevealColor, -1); - ta.recycle(); - } - //init paint - mBroadPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mBroadPaint.setStyle(Paint.Style.STROKE); - mBroadPaint.setColor(mBoardColor); - mBroadPaint.setStrokeWidth(mBoardWidth); - mBroadPaint.setDither(true); - - mCoverPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mCoverPaint.setStyle(Paint.Style.FILL); - mCoverPaint.setColor(DEFAULT_DISABLE_COVER_COLOR); - mCoverPaint.setDither(true); - - - mRevealBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mRevealBgPaint.setFilterBitmap(true); - mRevealBgPaint.setStyle(Paint.Style.FILL); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final float density = getContext().getResources().getDisplayMetrics().density; - final int defaultSize = (int) (DEFAULT_SIZE * density + 0.5); - int desiredWidth = getPaddingLeft() + getPaddingRight() + defaultSize; - int desiredHeight = getPaddingBottom() + getPaddingTop() + defaultSize; - int widthSpec = resolveSizeAndState(desiredWidth, widthMeasureSpec); - int heightSpec = resolveSizeAndState(desiredHeight, heightMeasureSpec); - super.onMeasure(widthSpec, heightSpec); - } - - public static int resolveSizeAndState(int desireSize, int measureSpec) { - int result = desireSize; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - switch (specMode) { - case MeasureSpec.UNSPECIFIED: - result = desireSize; - break; - case MeasureSpec.AT_MOST: - if (specSize < desireSize) { - result = specSize; - } else { - result = desireSize; - } - break; - case MeasureSpec.EXACTLY: - result = specSize; - break; - } - return result; - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - mAttachedToWindow = true; - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - mAttachedToWindow = false; - } - - @Override - protected int getSuggestedMinimumWidth() { - final float density = getContext().getResources().getDisplayMetrics().density; - return (int) (DEFAULT_SIZE * density + 0.5); - } - - @Override - protected int getSuggestedMinimumHeight() { - return getSuggestedMinimumWidth(); - } - - public void toggle() { - setChecked(!mChecked); - } - - public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { - mOnCheckedChangeListener = listener; - } - - private final void setProgress(int progress) { - if (mProgress != progress) { - this.mProgress = progress; - mFraction = mProgress * 1.0f / PROGRESS_MAX; -// if (BuildConfig.DEBUG) { -// Log.d(TAG, "setProgress: mProgress:" + mProgress + ",mFraction:" + mFraction); -// } - invalidate(); - } - } - - public final int getProgress() { - return mProgress; - } - - - public static long slastTime; - - - public boolean onDoubClick() { - boolean flag = false; - long time = System.currentTimeMillis() - slastTime; - if (time < 500) { - flag = true; - } - slastTime = System.currentTimeMillis(); - return flag; - } - - @Override - public boolean performClick() { - if (onDoubClick()) { - return false; - } - toggle(); - final boolean handled = super.performClick(); - if (!handled) { - // View only makes a sound effect if the onClickListener was - // called, so we'll need to make one here instead. - playSoundEffect(SoundEffectConstants.CLICK); - } - return handled; - } - - public void setChecked(boolean checked) { - if (mChecked != checked) { - mChecked = checked; - refreshDrawableState(); - // Avoid infinite recursions if setChecked() is called from a listener - if (mBroadcasting) { - return; - } - if (mAttachedToWindow) { - addAnim(checked); - } else { - cancelAnim(); - setProgress(checked ? PROGRESS_MAX : PROGRESS_MIN); - } - - mBroadcasting = true; - if (mOnCheckedChangeListener != null) { - mOnCheckedChangeListener.onCheckedChanged(this, mChecked); - } - mBroadcasting = false; - } - } - - private void cancelAnim() { - if (mCheckAnim != null) { - mCheckAnim.cancel(); - } - } - - - private void addAnim(boolean isChecked) { - mCheckAnim = ObjectAnimator.ofInt(this, "progress", isChecked ? PROGRESS_MAX : PROGRESS_MIN); - mCheckAnim.setDuration(300); - mCheckAnim.start(); - } - - private int generateCurColor() { - return (int) mArgbEvaluator.evaluate(mFraction, mUnCheckRevealColor, mCheckRevealColor); - } - - - public boolean isChecked() { - return mChecked; - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - canvas.save(); - canvas.translate(getPaddingLeft(), getPaddingTop()); - int width = getWidth() - getPaddingLeft() - getPaddingRight(); - int height = getHeight() - getPaddingBottom() - getPaddingTop(); - int radius = Math.min(width, height) / 2; - final Drawable buttonDrawable = mChecked ? mCheckedDrawable : mUncheckDrawable; - if (buttonDrawable != null) { - //// FIXME: 16-4-20 臨時使用 - if (mDrawableGravity == DRAWABLE_GRAVITY_LEFT) { - //偏右 - final int drawableHeight = buttonDrawable.getIntrinsicHeight(); - final int drawableWidth = buttonDrawable.getIntrinsicWidth(); - final int right = width / 2 - drawableWidth / 2; - final int left = right - drawableWidth; - final int top = (height - drawableHeight) / 2; - final int bottom = top + drawableHeight; - buttonDrawable.setBounds(left, top, right, bottom); - } else if (mDrawableGravity == DRAWABLE_GRAVITY_RIGHT) { - //偏左 - final int drawableHeight = buttonDrawable.getIntrinsicHeight(); - final int drawableWidth = buttonDrawable.getIntrinsicWidth(); - final int left = width / 2 + drawableWidth / 2; - final int right = left + drawableWidth; - final int top = (height - drawableHeight) / 2; - final int bottom = top + drawableHeight; - buttonDrawable.setBounds(left, top, right, bottom); - } else { - //居中 - final int drawableHeight = buttonDrawable.getIntrinsicHeight(); - final int drawableWidth = buttonDrawable.getIntrinsicWidth(); - final int left = (width - drawableWidth) / 2; - final int right = left + drawableWidth; - final int top = (height - drawableHeight) / 2; - final int bottom = top + drawableHeight; - buttonDrawable.setBounds(left, top, right, bottom); - } -// if (BuildConfig.DEBUG) { -// Log.v(TAG, "onDraw:button drawable bound" + buttonDrawable.getBounds()); -// } - } - if (mUnCheckRevealColor != -1 && !mChecked) { - mRevealBgPaint.setColor(mUnCheckRevealColor); - canvas.drawCircle(width / 2, height / 2, radius - mBoardWidth, mRevealBgPaint); - } - //draw broad - if (mBoardWidth > 0) { - canvas.drawCircle(width / 2, height / 2, radius - mBoardWidth / 2, mBroadPaint); - } - - mRevealBgPaint.setColor(generateCurColor()); - canvas.drawCircle(width / 2, height / 2, radius * mFraction, mRevealBgPaint); - - if (buttonDrawable != null) { - buttonDrawable.draw(canvas); - } - if (!isEnabled()) { - canvas.drawCircle(width / 2, height / 2, radius, mCoverPaint); - } - canvas.restore(); - } - - public void setDrawableGravity(int drawableGravity) { - if (mDrawableGravity != drawableGravity) { - mDrawableGravity = drawableGravity; - invalidate(); - } - } - - /** - * Interface definition for a callback to be invoked when the checked state - * of a compound button changed. - */ - public static interface OnCheckedChangeListener { - /** - * Called when the checked state of a compound button has changed. - * - * @param buttonView The compound button view whose state has changed. - * @param isChecked The new checked state of buttonView. - */ - void onCheckedChanged(SwitchButton buttonView, boolean isChecked); - } - - /** - * @author chensuilun - */ - static class SavedState extends BaseSavedState { - boolean mChecked; - - SavedState(Parcelable superState) { - super(superState); - } - - /** - * Constructor called from {@link #CREATOR} - */ - private SavedState(Parcel in) { - super(in); - mChecked = (Boolean) in.readValue(null); - } - - @Override - public void writeToParcel(Parcel out, int flags) { - super.writeToParcel(out, flags); - out.writeValue(mChecked); - } - - @Override - public String toString() { - return "CompoundButton.SavedState{" - + Integer.toHexString(System.identityHashCode(this)) - + " checked=" + mChecked + "}"; - } - - public static final Creator CREATOR - = new Creator() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } - - @Override - public Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); - - SavedState ss = new SavedState(superState); - - ss.mChecked = isChecked(); - return ss; - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - SavedState ss = (SavedState) state; - - super.onRestoreInstanceState(ss.getSuperState()); - setChecked(ss.mChecked); - requestLayout(); - } - -} diff --git a/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SwitchButton.kt b/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SwitchButton.kt new file mode 100644 index 0000000..ca1f525 --- /dev/null +++ b/app/src/main/java/github/hellocsl/cursorwheellayout/widget/SwitchButton.kt @@ -0,0 +1,428 @@ +package github.hellocsl.cursorwheellayout.widget + +import android.animation.ArgbEvaluator +import android.animation.ObjectAnimator +import android.annotation.TargetApi +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.drawable.Drawable +import android.os.Build +import android.os.Parcel +import android.os.Parcelable +import android.util.AttributeSet +import android.view.SoundEffectConstants +import android.view.View +import androidx.annotation.ColorInt +import github.hellocsl.cursorwheellayout.R + +/** + * + * + * Created by chensuilun on 16-4-13. + */ +class SwitchButton : View { + private var mDrawableGravity = DEFAULT_DRAWABLE_GRAVITY + + /** + * 画边界 + */ + private var mBroadPaint: Paint? = null + + /** + * 覆盖层 + */ + private var mCoverPaint: Paint? = null + + /** + * 画扩散进度 + */ + private var mRevealBgPaint: Paint? = null + + /** + * 边框颜色 + */ + @ColorInt + private val mBoardColor = DEFAULT_BOARD_COLOR + + /** + * 边框厚度 + */ + private var mBoardWidth = 0 + + /** + * 选中的时候的颜色 + */ + private var mCheckRevealColor = DEFAULT_BOARD_COLOR + + /** + * 未选中时候的颜色 + */ + private var mUnCheckRevealColor = DEFAULT_UNCHECK_REVEAL_COLOR + + /** + * 用于动画 0-100 选中的时候; + */ + private var mProgress = 0 + private var mChecked = false + private var mBroadcasting = false + private var mOnCheckedChangeListener: OnCheckedChangeListener? = null + + /** + * 未选中的时候的资源ID + */ + private var mUncheckDrawable: Drawable? = null + + /** + * 未选中的时候的资源ID + */ + private var mCheckedDrawable: Drawable? = null + private var mArgbEvaluator: ArgbEvaluator? = null + private var mFraction = 0f + private var mCheckAnim: ObjectAnimator? = null + private var mAttachedToWindow = false + + @JvmOverloads + constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : super( + context, + attrs, + defStyleAttr + ) { + init(context, attrs) + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + constructor( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int, + defStyleRes: Int + ) : super(context, attrs, defStyleAttr, defStyleRes) { + init(context, attrs) + } + + private fun init(context: Context, attrs: AttributeSet?) { + isClickable = true + mArgbEvaluator = ArgbEvaluator() + val density = context.resources.displayMetrics.density + mBoardWidth = (DEFAULT_BOARD_WIDTH * density + 0.5).toInt() + //TODO 更多自定义属性的获取,这里hardcode先,以后有需要在提取出来 + if (attrs != null) { + val ta = context.obtainStyledAttributes(attrs, R.styleable.SwitchButton) + val checkRes = + ta.getResourceId(R.styleable.SwitchButton_checkSrc, DEFAULT_CHECK_DRAWABLE_ID) + mCheckedDrawable = context.resources.getDrawable(checkRes) + val uncheckRes = + ta.getResourceId(R.styleable.SwitchButton_uncheckSrc, DEFAULT_UNCHECK_DRAWABLE_ID) + mUncheckDrawable = context.resources.getDrawable(uncheckRes) + mBoardWidth = + ta.getDimensionPixelOffset(R.styleable.SwitchButton_boardWidth, mBoardWidth) + mCheckRevealColor = + ta.getColor(R.styleable.SwitchButton_checkRevealColor, DEFAULT_CHECK_REVEAL_COLOR) + mUnCheckRevealColor = ta.getColor(R.styleable.SwitchButton_uncheckRevealColor, -1) + ta.recycle() + } + //init paint + mBroadPaint = Paint(Paint.ANTI_ALIAS_FLAG) + mBroadPaint!!.style = Paint.Style.STROKE + mBroadPaint!!.color = mBoardColor + mBroadPaint!!.strokeWidth = mBoardWidth.toFloat() + mBroadPaint!!.isDither = true + mCoverPaint = Paint(Paint.ANTI_ALIAS_FLAG) + mCoverPaint!!.style = Paint.Style.FILL + mCoverPaint!!.color = DEFAULT_DISABLE_COVER_COLOR + mCoverPaint!!.isDither = true + mRevealBgPaint = Paint(Paint.ANTI_ALIAS_FLAG) + mRevealBgPaint!!.isFilterBitmap = true + mRevealBgPaint!!.style = Paint.Style.FILL + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val density = context.resources.displayMetrics.density + val defaultSize = (DEFAULT_SIZE * density + 0.5).toInt() + val desiredWidth = paddingLeft + paddingRight + defaultSize + val desiredHeight = paddingBottom + paddingTop + defaultSize + val widthSpec = resolveSizeAndState(desiredWidth, widthMeasureSpec) + val heightSpec = resolveSizeAndState(desiredHeight, heightMeasureSpec) + super.onMeasure(widthSpec, heightSpec) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + mAttachedToWindow = true + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + mAttachedToWindow = false + } + + override fun getSuggestedMinimumWidth(): Int { + val density = context.resources.displayMetrics.density + return (DEFAULT_SIZE * density + 0.5).toInt() + } + + override fun getSuggestedMinimumHeight(): Int { + return suggestedMinimumWidth + } + + fun toggle() { + isChecked = !mChecked + } + + fun setOnCheckedChangeListener(listener: OnCheckedChangeListener?) { + mOnCheckedChangeListener = listener + } + + //if (BuildConfig.DEBUG) + //Log.d(TAG, "setProgress: mProgress:" + mProgress + ",mFraction:" + mFraction) + var progress: Int + get() = mProgress + private set(progress) { + if (mProgress != progress) { + mProgress = progress + mFraction = mProgress * 1.0f / PROGRESS_MAX + //if (BuildConfig.DEBUG) + //Log.d(TAG, "setProgress: mProgress:" + mProgress + ",mFraction:" + mFraction); + invalidate() + } + } + + private fun onDoubClick(): Boolean { + var flag = false + val time = System.currentTimeMillis() - slastTime + if (time < 500) { + flag = true + } + slastTime = System.currentTimeMillis() + return flag + } + + override fun performClick(): Boolean { + if (onDoubClick()) { + return false + } + toggle() + val handled = super.performClick() + if (!handled) { + // View only makes a sound effect if the onClickListener was + // called, so we'll need to make one here instead. + playSoundEffect(SoundEffectConstants.CLICK) + } + return handled + } + + private fun cancelAnim() { + if (mCheckAnim != null) { + mCheckAnim!!.cancel() + } + } + + private fun addAnim(isChecked: Boolean) { + mCheckAnim = + ObjectAnimator.ofInt(this, "progress", if (isChecked) PROGRESS_MAX else PROGRESS_MIN) + mCheckAnim?.duration = 300 + mCheckAnim?.start() + } + + private fun generateCurColor(): Int { + return mArgbEvaluator!!.evaluate(mFraction, mUnCheckRevealColor, mCheckRevealColor) as Int + } + + // Avoid infinite recursions if setChecked() is called from a listener + private var isChecked: Boolean + get() = mChecked + set(checked) { + if (mChecked != checked) { + mChecked = checked + refreshDrawableState() + // Avoid infinite recursions if setChecked() is called from a listener + if (mBroadcasting) { + return + } + if (mAttachedToWindow) { + addAnim(checked) + } else { + cancelAnim() + progress = if (checked) PROGRESS_MAX else PROGRESS_MIN + } + mBroadcasting = true + if (mOnCheckedChangeListener != null) { + mOnCheckedChangeListener!!.onCheckedChanged(this, mChecked) + } + mBroadcasting = false + } + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + canvas.save() + canvas.translate(paddingLeft.toFloat(), paddingTop.toFloat()) + val width = width - paddingLeft - paddingRight + val height = height - paddingBottom - paddingTop + val radius = width.coerceAtMost(height) / 2 + val buttonDrawable = if (mChecked) mCheckedDrawable else mUncheckDrawable + if (buttonDrawable != null) { + //// FIXME: 16-4-20 臨時使用 + when (mDrawableGravity) { + DRAWABLE_GRAVITY_LEFT -> { + //偏右 + val drawableHeight = buttonDrawable.intrinsicHeight + val drawableWidth = buttonDrawable.intrinsicWidth + val right = width / 2 - drawableWidth / 2 + val left = right - drawableWidth + val top = (height - drawableHeight) / 2 + val bottom = top + drawableHeight + buttonDrawable.setBounds(left, top, right, bottom) + } + DRAWABLE_GRAVITY_RIGHT -> { + //偏左 + val drawableHeight = buttonDrawable.intrinsicHeight + val drawableWidth = buttonDrawable.intrinsicWidth + val left = width / 2 + drawableWidth / 2 + val right = left + drawableWidth + val top = (height - drawableHeight) / 2 + val bottom = top + drawableHeight + buttonDrawable.setBounds(left, top, right, bottom) + } + else -> { + //居中 + val drawableHeight = buttonDrawable.intrinsicHeight + val drawableWidth = buttonDrawable.intrinsicWidth + val left = (width - drawableWidth) / 2 + val right = left + drawableWidth + val top = (height - drawableHeight) / 2 + val bottom = top + drawableHeight + buttonDrawable.setBounds(left, top, right, bottom) + } + } + + } + if (mUnCheckRevealColor != -1 && !mChecked) { + mRevealBgPaint!!.color = mUnCheckRevealColor + canvas.drawCircle( + width / 2.toFloat(), + height / 2.toFloat(), + radius - mBoardWidth.toFloat(), + mRevealBgPaint!! + ) + } + //draw broad + if (mBoardWidth > 0) { + canvas.drawCircle( + width / 2.toFloat(), + height / 2.toFloat(), + radius - mBoardWidth / 2.toFloat(), + mBroadPaint!! + ) + } + mRevealBgPaint!!.color = generateCurColor() + canvas.drawCircle( + width / 2.toFloat(), + height / 2.toFloat(), + radius * mFraction, + mRevealBgPaint!! + ) + buttonDrawable?.draw(canvas) + if (!isEnabled) { + canvas.drawCircle( + width / 2.toFloat(), + height / 2.toFloat(), + radius.toFloat(), + mCoverPaint!! + ) + } + canvas.restore() + } + + fun setDrawableGravity(drawableGravity: Int) { + if (mDrawableGravity != drawableGravity) { + mDrawableGravity = drawableGravity + invalidate() + } + } + + /** + * Interface definition for a callback to be invoked when the checked state + * of a compound button changed. + */ + interface OnCheckedChangeListener { + /** + * Called when the checked state of a compound button has changed. + * + * @param buttonView The compound button view whose state has changed. + * @param isChecked The new checked state of buttonView. + */ + fun onCheckedChanged(buttonView: SwitchButton?, isChecked: Boolean) + } + + /** + * @author chensuilun + */ + internal class SavedState(superState: Parcelable?) : BaseSavedState(superState) { + var mChecked = false + + override fun writeToParcel(out: Parcel, flags: Int) { + super.writeToParcel(out, flags) + out.writeValue(mChecked) + } + + override fun toString(): String { + return ("CompoundButton.SavedState{" + + Integer.toHexString(System.identityHashCode(this)) + + " checked=" + mChecked + "}") + } + } + + public override fun onSaveInstanceState(): Parcelable? { + val superState = super.onSaveInstanceState() + val ss = SavedState(superState) + ss.mChecked = isChecked + return ss + } + + public override fun onRestoreInstanceState(state: Parcelable) { + val ss = state as SavedState + super.onRestoreInstanceState(ss.superState) + isChecked = ss.mChecked + requestLayout() + } + + companion object { + private const val TAG = "SwitchButton" + private const val PROGRESS_MIN = 0 + private const val PROGRESS_MAX = 100 + private const val DEFAULT_BOARD_WIDTH = 4 // dp + private const val DEFAULT_BOARD_COLOR = -0xc3b6ae + private const val DEFAULT_UNCHECK_REVEAL_COLOR = -0xc3b6ae + + //DRAWABLE GRAVITY + const val DRAWABLE_GRAVITY_LEFT = 0 + const val DRAWABLE_GRAVITY_RIGHT = 1 + const val DEFAULT_DRAWABLE_GRAVITY = -1 + + // private static final int DEFAULT_UNCHECK_REVEAL_COLOR = 0X1D1F22; + private const val DEFAULT_CHECK_REVEAL_COLOR = -0x3ad6 + private const val DEFAULT_DISABLE_COVER_COLOR = 0x4cffffff + private const val DEFAULT_CHECK_DRAWABLE_ID = R.mipmap.ic_launcher + private const val DEFAULT_UNCHECK_DRAWABLE_ID = R.mipmap.ic_launcher + private const val DEFAULT_SIZE = 126 //dp + fun resolveSizeAndState(desireSize: Int, measureSpec: Int): Int { + var result = desireSize + val specMode = MeasureSpec.getMode(measureSpec) + val specSize = MeasureSpec.getSize(measureSpec) + when (specMode) { + MeasureSpec.UNSPECIFIED -> result = desireSize + MeasureSpec.AT_MOST -> result = if (specSize < desireSize) { + specSize + } else { + desireSize + } + MeasureSpec.EXACTLY -> result = specSize + } + return result + } + + var slastTime: Long = 0 + } +} \ 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 index e5cd3e4..e787b54 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,82 +1,71 @@ - + xmlns:tools="http://schemas.android.com/tools"> + - + - - + + - + - - + - - - - + + -