diff --git a/DEV/default-detekt-config.yml b/DEV/default-detekt-config.yml index c40f96709..a6049cf9e 100644 --- a/DEV/default-detekt-config.yml +++ b/DEV/default-detekt-config.yml @@ -68,7 +68,8 @@ complexity: threshold: 60 LongParameterList: active: true - threshold: 10 + functionThreshold: 10 + constructorThreshold: 10 ignoreDefaultParameters: false MethodOverloading: active: false @@ -114,7 +115,7 @@ empty-blocks: active: true EmptyFunctionBlock: active: false - ignoreOverriddenFunctions: false + ignoreOverridden: false EmptyIfBlock: active: true EmptyInitBlock: @@ -311,7 +312,7 @@ naming: excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt" parameterPattern: '[a-z][A-Za-z0-9]*' excludeClassPattern: '$^' - ignoreOverriddenFunctions: true + ignoreOverridden: true InvalidPackageDeclaration: active: false rootPackage: '' @@ -319,7 +320,7 @@ naming: active: true MemberNameEqualsClassName: active: false - ignoreOverriddenFunction: true + ignoreOverridden: true ObjectPropertyNaming: active: true excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt" diff --git a/Gemfile.lock b/Gemfile.lock index 881771cd8..1e841c989 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - addressable (2.7.0) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) ansi (1.5.0) ast (2.4.2) @@ -58,7 +58,7 @@ GEM open4 (1.3.4) public_suffix (4.0.6) rchardet (1.8.0) - rexml (3.2.4) + rexml (3.2.5) ruby-ll (2.1.2) ansi ast diff --git a/README.md b/README.md index 597a97a9a..9a150c0e9 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ It's blazing fast, minimizing the code you need to write, and is easy to extend. ## Latest releases 🛠 -- Kotlin | [v5.4.1](https://github.com/mikepenz/FastAdapter/tree/v5.4.1) +- Kotlin | [v5.5.0](https://github.com/mikepenz/FastAdapter/tree/v5.5.0) - Java && AndroidX | [v3.3.1](https://github.com/mikepenz/FastAdapter/tree/v3.3.1) - Java && AppCompat | [v3.2.9](https://github.com/mikepenz/FastAdapter/tree/v3.2.9) diff --git a/app/build.gradle b/app/build.gradle index 8995a9307..1f1b1b219 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -133,8 +133,8 @@ dependencies { //https://github.com/mikepenz/Android-Iconics implementation 'com.mikepenz:material-design-iconic-typeface:2.2.0.8-kotlin@aar' implementation 'com.mikepenz:community-material-typeface:5.8.55.0-kotlin@aar' - implementation 'com.mikepenz:google-material-typeface:4.0.0.1-kotlin@aar' - implementation 'com.mikepenz:fontawesome-typeface:5.9.0.2-kotlin@aar' + implementation 'com.mikepenz:google-material-typeface:4.0.0.2-kotlin@aar' + implementation 'com.mikepenz:fontawesome-typeface:5.13.3.0-kotlin@aar' //Used for the StickyHeaderSample //https://github.com/timehop/sticky-headers-recyclerview @@ -148,7 +148,7 @@ dependencies { //used to load the images in the ImageListSample //https://github.com/coil-kt/coil - implementation 'io.coil-kt:coil:1.1.1' + implementation 'io.coil-kt:coil:1.3.2' //Used to provide the drag selection like google photos implementation 'com.github.MFlisar:DragSelectRecyclerView:0.3' @@ -191,6 +191,6 @@ buildscript { } dependencies { - classpath "io.realm:realm-gradle-plugin:10.4.0" + classpath "io.realm:realm-gradle-plugin:10.8.0" } } \ No newline at end of file diff --git a/app/src/main/java/com/mikepenz/fastadapter/app/PagedActivity.kt b/app/src/main/java/com/mikepenz/fastadapter/app/PagedActivity.kt index 821465f67..0127c5532 100755 --- a/app/src/main/java/com/mikepenz/fastadapter/app/PagedActivity.kt +++ b/app/src/main/java/com/mikepenz/fastadapter/app/PagedActivity.kt @@ -1,7 +1,11 @@ package com.mikepenz.fastadapter.app +import android.graphics.Color import android.os.Bundle import android.os.Handler +import android.view.Menu +import android.view.MenuItem +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.AsyncDifferConfig @@ -14,6 +18,10 @@ import com.mikepenz.fastadapter.app.paged.DemoEntity import com.mikepenz.fastadapter.app.paged.DemoEntityViewModel import com.mikepenz.fastadapter.paged.PagedModelAdapter import com.mikepenz.fastadapter.select.getSelectExtension +import com.mikepenz.iconics.IconicsDrawable +import com.mikepenz.iconics.typeface.library.materialdesigniconic.MaterialDesignIconic +import com.mikepenz.iconics.utils.actionBar +import com.mikepenz.iconics.utils.colorInt class PagedActivity : AppCompatActivity() { @@ -25,6 +33,8 @@ class PagedActivity : AppCompatActivity() { //save our FastAdapter private lateinit var mItemAdapter: PagedModelAdapter + private lateinit var viewModel: DemoEntityViewModel + override fun onCreate(savedInstanceState: Bundle?) { //create the activity super.onCreate(savedInstanceState) @@ -36,22 +46,27 @@ class PagedActivity : AppCompatActivity() { setSupportActionBar(binding.toolbar) supportActionBar?.setTitle(R.string.sample_paged_list) - val asyncDifferConfig = AsyncDifferConfig.Builder(object : DiffUtil.ItemCallback() { - override fun areItemsTheSame(oldItem: DemoEntity, newItem: DemoEntity): Boolean { - return oldItem.identifier == newItem.identifier - } + val asyncDifferConfig = + AsyncDifferConfig.Builder(object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: DemoEntity, newItem: DemoEntity): Boolean { + return oldItem.identifier == newItem.identifier + } - override fun areContentsTheSame(oldItem: DemoEntity, newItem: DemoEntity): Boolean { - return oldItem == newItem - } - }).build() + override fun areContentsTheSame(oldItem: DemoEntity, newItem: DemoEntity): Boolean { + return oldItem.data1 == newItem.data1 + } + }).build() //create our ItemAdapter which will host our items - mItemAdapter = PagedModelAdapter(asyncDifferConfig, { arg: Int -> SimpleImageItem().setPlaceholder() }) { - SimpleImageItem().withName(it.data1 ?: "").withDescription(it.data2 ?: "").apply { + mItemAdapter = PagedModelAdapter( + asyncDifferConfig, + { SimpleImageItem().setPlaceholder() }) { + SimpleImageItem().apply { identifier = it.identifier.toLong() isSelectable = true withImage("https://raw.githubusercontent.com/mikepenz/earthview-wallpapers/develop/thumb/yang_zhuo_yong_cuo,_tibet-china-63.jpg") + withName(it.data1 ?: "") + withDescription(it.data2 ?: "") } } @@ -67,14 +82,17 @@ class PagedActivity : AppCompatActivity() { binding.rv.layoutManager = LinearLayoutManager(this) binding.rv.adapter = mFastAdapter - val viewModel = ViewModelProvider(this, DemoEntityViewModel.DemoEntityViewModelFactory(this.application)) + viewModel = ViewModelProvider( + this, + DemoEntityViewModel.DemoEntityViewModelFactory(this.application) + ) .get(DemoEntityViewModel::class.java) //listen to data changes and pass it to adapter for displaying in recycler view viewModel.demoEntitiesList.observe(this, { t -> mItemAdapter.submitList(t!!) }) //if we do this. the first added items will be animated :D - Handler().postDelayed({ + Handler(mainLooper).postDelayed({ //restore selections (this has to be done after the items were added mFastAdapter.withSavedInstanceState(savedInstanceState) }, 50) @@ -92,6 +110,32 @@ class PagedActivity : AppCompatActivity() { super.onSaveInstanceState(outState) } + override fun onCreateOptionsMenu(menu: Menu): Boolean { + val inflater = menuInflater + inflater.inflate(R.menu.refresh, menu) + menu.findItem(R.id.item_refresh).icon = + IconicsDrawable(this, MaterialDesignIconic.Icon.gmi_refresh).apply { + colorInt = Color.BLACK; actionBar() + } + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + //handle the click on the back arrow click + return when (item.itemId) { + android.R.id.home -> { + onBackPressed() + true + } + R.id.item_refresh -> { + viewModel.updateEntities() + Toast.makeText(this, "Refresh DB", Toast.LENGTH_SHORT).show() + true + } + else -> super.onOptionsItemSelected(item) + } + } + override fun onSupportNavigateUp(): Boolean { onBackPressed() return true diff --git a/app/src/main/java/com/mikepenz/fastadapter/app/SwipeDrawerListActivity.kt b/app/src/main/java/com/mikepenz/fastadapter/app/SwipeDrawerListActivity.kt index d7fed25b3..fc1d584f5 100644 --- a/app/src/main/java/com/mikepenz/fastadapter/app/SwipeDrawerListActivity.kt +++ b/app/src/main/java/com/mikepenz/fastadapter/app/SwipeDrawerListActivity.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.text.TextUtils import android.view.Menu import android.view.MenuItem +import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.SearchView @@ -12,6 +13,7 @@ import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.mikepenz.fastadapter.IAdapter import com.mikepenz.fastadapter.adapters.FastItemAdapter import com.mikepenz.fastadapter.app.adapters.IDraggableViewHolder import com.mikepenz.fastadapter.app.databinding.ActivitySampleBinding @@ -28,7 +30,8 @@ import com.mikepenz.iconics.utils.colorInt import io.reactivex.functions.Consumer import java.util.* -class SwipeDrawerListActivity : AppCompatActivity(), ItemTouchCallback, SimpleSwipeDrawerCallback.ItemSwipeCallback { +class SwipeDrawerListActivity : AppCompatActivity(), ItemTouchCallback, + SimpleSwipeDrawerCallback.ItemSwipeCallback { private lateinit var binding: ActivitySampleBinding //save our FastAdapter @@ -78,9 +81,20 @@ class SwipeDrawerListActivity : AppCompatActivity(), ItemTouchCallback, SimpleSw //create our FastAdapter which will manage everything fastItemDrawerAdapter = FastItemAdapter() //configure the itemAdapter - fastItemDrawerAdapter.itemFilter.filterPredicate = { item: SwipeableDrawerItem, constraint: CharSequence? -> - item.name?.textString.toString().contains(constraint.toString(), ignoreCase = true) - } + fastItemDrawerAdapter.itemFilter.filterPredicate = + { item: SwipeableDrawerItem, constraint: CharSequence? -> + item.name?.textString.toString().contains(constraint.toString(), ignoreCase = true) + } + + + // Item click listener + fastItemDrawerAdapter.onClickListener = + { _: View?, _: IAdapter, _: SwipeableDrawerItem, pos: Int -> + run { + println("click! $pos") + true + } + } //get our recyclerView and do basic setup binding.rv.layoutManager = LinearLayoutManager(this) @@ -110,16 +124,18 @@ class SwipeDrawerListActivity : AppCompatActivity(), ItemTouchCallback, SimpleSw //add drag and drop for item //and add swipe as well touchCallback = SimpleSwipeDrawerDragCallback( - this, - ItemTouchHelper.LEFT, - this) - .withNotifyAllDrops(true) - .withSwipeLeft(80) // Width of delete button - .withSwipeRight(160) // Width of archive and share buttons - .withSensitivity(10f) - .withSurfaceThreshold(0.3f) - - touchHelper = ItemTouchHelper(touchCallback) // Create ItemTouchHelper and pass with parameter the SimpleDragCallback + this, + ItemTouchHelper.LEFT, + this + ) + .withNotifyAllDrops(true) + .withSwipeLeft(80) // Width of delete button + .withSwipeRight(160) // Width of archive and share buttons + .withSensitivity(10f) + .withSurfaceThreshold(0.3f) + + touchHelper = + ItemTouchHelper(touchCallback) // Create ItemTouchHelper and pass with parameter the SimpleDragCallback touchHelper.attachToRecyclerView(binding.rv) // Attach ItemTouchHelper to RecyclerView //restore selections (this has to be done after the items were added) @@ -155,7 +171,10 @@ class SwipeDrawerListActivity : AppCompatActivity(), ItemTouchCallback, SimpleSw inflater.inflate(R.menu.search, menu) //search icon - menu.findItem(R.id.search).icon = IconicsDrawable(this, MaterialDesignIconic.Icon.gmi_search).apply { colorInt = Color.BLACK; actionBar() } + menu.findItem(R.id.search).icon = + IconicsDrawable(this, MaterialDesignIconic.Icon.gmi_search).apply { + colorInt = Color.BLACK; actionBar() + } val searchView = menu.findItem(R.id.search).actionView as SearchView searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { @@ -177,7 +196,11 @@ class SwipeDrawerListActivity : AppCompatActivity(), ItemTouchCallback, SimpleSw } override fun itemTouchOnMove(oldPosition: Int, newPosition: Int): Boolean { - DragDropUtil.onMove(fastItemDrawerAdapter.itemAdapter, oldPosition, newPosition) // change position + DragDropUtil.onMove( + fastItemDrawerAdapter.itemAdapter, + oldPosition, + newPosition + ) // change position return true } @@ -196,7 +219,34 @@ class SwipeDrawerListActivity : AppCompatActivity(), ItemTouchCallback, SimpleSw } companion object { - private val ALPHABET = arrayOf("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z") + private val ALPHABET = arrayOf( + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z" + ) } override fun itemSwiped(position: Int, direction: Int) { diff --git a/app/src/main/java/com/mikepenz/fastadapter/app/items/SimpleImageItem.kt b/app/src/main/java/com/mikepenz/fastadapter/app/items/SimpleImageItem.kt index 873038696..e3d786e5d 100644 --- a/app/src/main/java/com/mikepenz/fastadapter/app/items/SimpleImageItem.kt +++ b/app/src/main/java/com/mikepenz/fastadapter/app/items/SimpleImageItem.kt @@ -23,7 +23,8 @@ class SimpleImageItem : BaseItem() { private var mImageUrl: String? = null private var mName: String? = null private var mDescription: String? = null - private var isPlaceholder: Boolean = false // True when used as placeholderInterceptor by PagedModelAdapter + private var isPlaceholder: Boolean = + false // True when used as placeholderInterceptor by PagedModelAdapter /** * defines the type defining this item. must be unique. preferably an id @@ -85,10 +86,18 @@ class SimpleImageItem : BaseItem() { holder.imageView.setImageBitmap(null) //set the background for the item - val color = ctx.getThemeColor(R.attr.colorPrimary, ContextCompat.getColor(ctx, R.color.colorPrimary)) + val color = ctx.getThemeColor( + R.attr.colorPrimary, + ContextCompat.getColor(ctx, R.color.colorPrimary) + ) holder.view.clearAnimation() - holder.view.foreground = FastAdapterUIUtils.getSelectablePressedBackground(ctx, FastAdapterUIUtils.adjustAlpha(color, 100), 50, true) + holder.view.foreground = FastAdapterUIUtils.getSelectablePressedBackground( + ctx, + FastAdapterUIUtils.adjustAlpha(color, 100), + 50, + true + ) //load glide holder.imageView.load(mImageUrl) { diff --git a/app/src/main/java/com/mikepenz/fastadapter/app/items/SwipeableDrawerItem.kt b/app/src/main/java/com/mikepenz/fastadapter/app/items/SwipeableDrawerItem.kt index 2b0e67100..be9d958d7 100644 --- a/app/src/main/java/com/mikepenz/fastadapter/app/items/SwipeableDrawerItem.kt +++ b/app/src/main/java/com/mikepenz/fastadapter/app/items/SwipeableDrawerItem.kt @@ -131,6 +131,10 @@ class SwipeableDrawerItem : AbstractItem(), ISwi shareBtn.setOnClickListener { shareActionRunnable?.run() } + // Important : trigger the ViewHolder's global onClick event + itemContent.setOnClickListener { + (it.parent as View).performClick() + } } override fun onDropped() { diff --git a/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntitiesDataSourceFactory.kt b/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntitiesDataSourceFactory.kt deleted file mode 100644 index 73da65f1d..000000000 --- a/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntitiesDataSourceFactory.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.mikepenz.fastadapter.app.paged - -import android.content.Context - -import androidx.paging.DataSource - -/** - * https://www.zoftino.com/pagination-in-android-using-paging-library - */ -class DemoEntitiesDataSourceFactory(private val ctx: Context) : DataSource.Factory() { - private var demoEntitiesDataSource: DemoEntityDataSource? = null - - override fun create(): DataSource { - if (demoEntitiesDataSource == null) { - demoEntitiesDataSource = DemoEntityDataSource(ctx) - } - return demoEntitiesDataSource!! - } -} \ No newline at end of file diff --git a/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityDataSource.kt b/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityDataSource.kt deleted file mode 100644 index 754bd92a8..000000000 --- a/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityDataSource.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.mikepenz.fastadapter.app.paged - -import android.content.Context -import androidx.paging.PageKeyedDataSource - -/** - * https://www.zoftino.com/pagination-in-android-using-paging-library - */ -//data source for PagedList, it is used for loading data for each page -class DemoEntityDataSource(ctx: Context) : PageKeyedDataSource() { - private val demoEntityDAO: DemoEntityLocalDAO = LocalRepository.getDemoEntityDB(ctx).demoEntityDAO() - - //is called too load initial data - override fun loadInitial(params: LoadInitialParams, - callback: LoadInitialCallback) { - - var cpns = demoEntityDAO.getDemoEntitiesBySize(0, params.requestedLoadSize) - - //this is required to handle first request after db is created or app is installed - var noOfTryies = 0 - while (cpns.isEmpty()) { - cpns = demoEntityDAO.getDemoEntitiesBySize(0, params.requestedLoadSize) - noOfTryies++ - if (noOfTryies == 6) { - break - } - try { - Thread.sleep(500) - } catch (e: InterruptedException) { - // no action - } - } - - callback.onResult(cpns, null, cpns.size + 1) - } - - override fun loadBefore(params: LoadParams, callback: LoadCallback) { - } - - //is called to load pages of data using key passed in params - override fun loadAfter(params: LoadParams, callback: LoadCallback) { - val cpns = demoEntityDAO.getDemoEntitiesBySize(params.key, params.requestedLoadSize) - - Thread.sleep(500) - - val nextKey = params.key + cpns.size - callback.onResult(cpns, nextKey) - } -} diff --git a/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityLocalDAO.kt b/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityLocalDAO.kt index 2ee106b5d..80306ae07 100644 --- a/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityLocalDAO.kt +++ b/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityLocalDAO.kt @@ -1,19 +1,24 @@ package com.mikepenz.fastadapter.app.paged +import androidx.paging.DataSource import androidx.room.Dao import androidx.room.Insert import androidx.room.Query + /** * https://www.zoftino.com/pagination-in-android-using-paging-library */ @Dao interface DemoEntityLocalDAO { //to fetch data required to display in each page - @Query("SELECT * FROM DemoEntity WHERE identifier >= :id ORDER BY identifier LIMIT :size") - fun getDemoEntitiesBySize(id: Int, size: Int): List + @Query("SELECT * FROM DemoEntity") + fun getAll(): DataSource.Factory //this is used to populate db @Insert fun insertDemoEntities(demoEntities: List) + + @Query("UPDATE DemoEntity SET data1 = -data1") + fun updateDemoEntities() } \ No newline at end of file diff --git a/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityViewModel.kt b/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityViewModel.kt index d61876b30..cce2fa798 100644 --- a/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityViewModel.kt +++ b/app/src/main/java/com/mikepenz/fastadapter/app/paged/DemoEntityViewModel.kt @@ -1,39 +1,46 @@ package com.mikepenz.fastadapter.app.paged import android.app.Application - import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.paging.LivePagedListBuilder import androidx.paging.PagedList +import io.reactivex.Completable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers + /** * https://www.zoftino.com/pagination-in-android-using-paging-library */ -class DemoEntityViewModel(application: Application) : ViewModel() { +class DemoEntityViewModel(val application: Application) : ViewModel() { //PagedList controls data loading using data source + private val dao: DemoEntityLocalDAO = + LocalRepository.getDemoEntityDB(application).demoEntityDAO() var demoEntitiesList: LiveData> init { - //instantiate DemoEntitiesDataSourceFactory - val factory = DemoEntitiesDataSourceFactory(application) + val pagedListConfig = PagedList.Config.Builder() + .setPageSize(20) + .setPrefetchDistance(20) + .setEnablePlaceholders(true) + .build() - //create PagedList Config - val config = PagedList.Config.Builder() - .setEnablePlaceholders(true) - .setInitialLoadSizeHint(10) - .setPageSize(5) - .build() + demoEntitiesList = LivePagedListBuilder(dao.getAll(), pagedListConfig).build() + } - //create LiveData object using LivePagedListBuilder which takes - //data source factory and page config as params - demoEntitiesList = LivePagedListBuilder(factory, config).build() + fun updateEntities() { + Completable.fromRunnable { dao.updateDemoEntities() } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe() } //factory for creating view model, // required because we need to pass Application to view model object - class DemoEntityViewModelFactory(private val mApplication: Application) : ViewModelProvider.NewInstanceFactory() { + class DemoEntityViewModelFactory(private val mApplication: Application) : + ViewModelProvider.NewInstanceFactory() { override fun create(viewModel: Class): T { return DemoEntityViewModel(mApplication) as T } diff --git a/app/src/main/res/layout/swipeable_drawer_item.xml b/app/src/main/res/layout/swipeable_drawer_item.xml index c19a6cfa2..c141d7e66 100644 --- a/app/src/main/res/layout/swipeable_drawer_item.xml +++ b/app/src/main/res/layout/swipeable_drawer_item.xml @@ -3,7 +3,10 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="@dimen/material_drawer_item_primary"> + android:layout_height="@dimen/material_drawer_item_primary" + android:clickable="true" + android:focusable="true" + android:longClickable="true"> : EndlessRecyclerOnScrollListener { * An overload of [withNewItemsDeliveredTo()][withNewItemsDeliveredTo] * that allows additional callbacks. */ - fun withNewItemsDeliveredTo(itemAdapter: IItemAdapter<*, Item>, itemFactory: (element: Model) -> Item?, extraOnNewItemsListener: OnNewItemsListener): EndlessScrollHelper { + fun withNewItemsDeliveredTo( + itemAdapter: IItemAdapter<*, Item>, + itemFactory: (element: Model) -> Item?, + extraOnNewItemsListener: OnNewItemsListener + ): EndlessScrollHelper { onNewItemsListener = DeliverToIItemAdapter2(itemAdapter, itemFactory, extraOnNewItemsListener) return this } @@ -180,9 +184,10 @@ open class EndlessScrollHelper : EndlessRecyclerOnScrollListener { onLoadMore(ResultReceiverImpl(this, currentPage), currentPage) } - private class ResultReceiverImpl internal constructor(helper: EndlessScrollHelper, override val receiverPage: Int) + private class ResultReceiverImpl(helper: EndlessScrollHelper, override val receiverPage: Int) : + WeakReference>(helper), ResultReceiver, Runnable { // We use WeakReferences to outer class to avoid memory leaks. - : WeakReference>(helper), ResultReceiver, Runnable { + private var helperStrongRef: EndlessScrollHelper? = null private var result: List? = null @@ -225,7 +230,10 @@ open class EndlessScrollHelper : EndlessRecyclerOnScrollListener { //----------------------------------------- //----------------------------------------- - private open class DeliverToIItemAdapter internal constructor(private val itemAdapter: IItemAdapter<*, Item>, private val itemFactory: (element: Model) -> Item?) : OnNewItemsListener { + private open class DeliverToIItemAdapter internal constructor( + private val itemAdapter: IItemAdapter<*, Item>, + private val itemFactory: (element: Model) -> Item? + ) : OnNewItemsListener { override fun onNewItems(newItems: List, page: Int) { val items = newItems.mapNotNull(itemFactory) @@ -239,14 +247,21 @@ open class EndlessScrollHelper : EndlessRecyclerOnScrollListener { } } - private class DeliverToIItemAdapter2 internal constructor(itemAdapter: IItemAdapter<*, Item>, itemFactory: (element: Model) -> Item?, private val extraOnNewItemsListener: OnNewItemsListener) : DeliverToIItemAdapter(itemAdapter, itemFactory) { + private class DeliverToIItemAdapter2 internal constructor( + itemAdapter: IItemAdapter<*, Item>, + itemFactory: (element: Model) -> Item?, + private val extraOnNewItemsListener: OnNewItemsListener + ) : DeliverToIItemAdapter(itemAdapter, itemFactory) { override fun onNewItems(newItems: List, page: Int) { extraOnNewItemsListener.onNewItems(newItems, page) super.onNewItems(newItems, page) } } - private class DeliverToModelAdapter2 internal constructor(modelItemAdapter: ModelAdapter, private val extraOnNewItemsListener: OnNewItemsListener) : DeliverToModelAdapter(modelItemAdapter) { + private class DeliverToModelAdapter2 internal constructor( + modelItemAdapter: ModelAdapter, + private val extraOnNewItemsListener: OnNewItemsListener + ) : DeliverToModelAdapter(modelItemAdapter) { override fun onNewItems(newItems: List, page: Int) { extraOnNewItemsListener.onNewItems(newItems, page) super.onNewItems(newItems, page) diff --git a/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/Extensions.kt b/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/Extensions.kt new file mode 100644 index 000000000..54667f7f8 --- /dev/null +++ b/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/Extensions.kt @@ -0,0 +1,17 @@ +package com.mikepenz.fastadapter.swipe + +import androidx.recyclerview.widget.ItemTouchHelper + +/** + * Retrieve the swipe directions allowed for this [ISwipeable] element. + */ +internal fun ISwipeable.getSwipeDirs(dirs: Int): Int { + var directions = dirs + if (!isDirectionSupported(ItemTouchHelper.LEFT)) { + directions = dirs and ItemTouchHelper.LEFT.inv() + } + if (!isDirectionSupported(ItemTouchHelper.RIGHT)) { + directions = dirs and ItemTouchHelper.RIGHT.inv() + } + return directions +} \ No newline at end of file diff --git a/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/ISwipeable.kt b/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/ISwipeable.kt index 8bf95691f..b393cf4c5 100644 --- a/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/ISwipeable.kt +++ b/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/ISwipeable.kt @@ -6,4 +6,11 @@ package com.mikepenz.fastadapter.swipe interface ISwipeable { /** @return true if swipeable */ val isSwipeable: Boolean + + /** + * @return true if the provided direction is supported + * + * This function will only be called if [isSwipeable] returns true + */ + fun isDirectionSupported(direction: Int): Boolean = true } diff --git a/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/SimpleSwipeCallback.kt b/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/SimpleSwipeCallback.kt index d2f74e249..40d062613 100644 --- a/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/SimpleSwipeCallback.kt +++ b/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/SimpleSwipeCallback.kt @@ -95,7 +95,7 @@ class SimpleSwipeCallback @JvmOverloads constructor(private val itemSwipeCallbac val item = FastAdapter.getHolderAdapterItem>(viewHolder) return if (item is ISwipeable) { if ((item as ISwipeable).isSwipeable) { - super.getSwipeDirs(recyclerView, viewHolder) + item.getSwipeDirs(super.getSwipeDirs(recyclerView, viewHolder)) } else { 0 } @@ -107,7 +107,7 @@ class SimpleSwipeCallback @JvmOverloads constructor(private val itemSwipeCallbac override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { viewHolder.itemView.translationX = 0f viewHolder.itemView.translationY = 0f - val position = viewHolder.adapterPosition + val position = viewHolder.bindingAdapterPosition if (position != RecyclerView.NO_POSITION) { itemSwipeCallback.itemSwiped(position, direction) } @@ -129,7 +129,7 @@ class SimpleSwipeCallback @JvmOverloads constructor(private val itemSwipeCallbac //Inspired/modified from: https://github.com/nemanja-kovacevic/recycler-view-swipe-to-delete/blob/master/app/src/main/java/net/nemanjakovacevic/recyclerviewswipetodelete/MainActivity.java override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) { val itemView = viewHolder.itemView - if (viewHolder.adapterPosition == RecyclerView.NO_POSITION) { + if (viewHolder.bindingAdapterPosition == RecyclerView.NO_POSITION) { return } if (abs(dX) > abs(dY)) { diff --git a/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/SimpleSwipeDrawerCallback.kt b/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/SimpleSwipeDrawerCallback.kt index 8489e4ea3..0fe7a2e8f 100644 --- a/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/SimpleSwipeDrawerCallback.kt +++ b/fastadapter-extensions-swipe/src/main/java/com/mikepenz/fastadapter/swipe/SimpleSwipeDrawerCallback.kt @@ -102,7 +102,7 @@ class SimpleSwipeDrawerCallback @JvmOverloads constructor(private val swipeDirs: val item = FastAdapter.getHolderAdapterItem>(viewHolder) return if (item is ISwipeable) { if ((item as ISwipeable).isSwipeable) { - super.getSwipeDirs(recyclerView, viewHolder) + item.getSwipeDirs(super.getSwipeDirs(recyclerView, viewHolder)) } else { 0 } @@ -112,7 +112,7 @@ class SimpleSwipeDrawerCallback @JvmOverloads constructor(private val swipeDirs: } override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { - val position = viewHolder.adapterPosition + val position = viewHolder.bindingAdapterPosition val id = viewHolder.itemId if (position != RecyclerView.NO_POSITION && (!swipedStates.containsKey(id) || swipedStates[id] != direction)) { itemSwipeCallback?.itemSwiped(position, direction) @@ -146,7 +146,7 @@ class SimpleSwipeDrawerCallback @JvmOverloads constructor(private val swipeDirs: touchTransmitterSet = true } - val position = viewHolder.adapterPosition + val position = viewHolder.bindingAdapterPosition if (position == RecyclerView.NO_POSITION) return @@ -160,7 +160,7 @@ class SimpleSwipeDrawerCallback @JvmOverloads constructor(private val swipeDirs: // If unswiped, fire event and update swiped state if (0f == dX && swipedStates.containsKey(viewHolder.itemId)) { - itemSwipeCallback?.itemUnswiped(viewHolder.adapterPosition) + itemSwipeCallback?.itemUnswiped(viewHolder.bindingAdapterPosition) swipedStates.remove(viewHolder.itemId) } diff --git a/fastadapter/build.gradle b/fastadapter/build.gradle index 1c4880a12..067cc1284 100644 --- a/fastadapter/build.gradle +++ b/fastadapter/build.gradle @@ -42,7 +42,7 @@ dependencies { api "androidx.recyclerview:recyclerview:${versions.recyclerView}" api "androidx.appcompat:appcompat:${versions.appcompat}" - testImplementation 'junit:junit:4.13.1' + testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-all:1.10.19' testImplementation "org.robolectric:robolectric:${versions.roboelectric}" testImplementation 'com.squareup.assertj:assertj-android:1.2.0' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8cf6eb5ad..a0f7639f7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists