John
John

Reputation: 27

Crash on setOnTabSelectedListener with com.android.support:design:28.0.0

I'm using a library with a class that extends TabLayout. I'm trying to build with the latest support libraries:

implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:preference-v14:28.0.0'
implementation 'com.android.support:support-v13:28.0.0'

This results in a crash:

java.lang.NoSuchMethodError: No virtual method setOnTabSelectedListener(Landroid/support/design/widget/TabLayout$OnTabSelectedListener;)

This is the source from the decompiled TabLayout.class file (It doesn't seem to have a source jar like other versions):

/** @deprecated */
@Deprecated
public void setOnTabSelectedListener(@Nullable TabLayout.BaseOnTabSelectedListener listener) { ... }

public interface OnTabSelectedListener extends TabLayout.BaseOnTabSelectedListener<TabLayout.Tab> {
}

public interface BaseOnTabSelectedListener<T extends TabLayout.Tab> { ... }

It works with 27.1.1 and earlier versions where the source looks like so:

/**
 * @deprecated Use {@link #addOnTabSelectedListener(OnTabSelectedListener)} and
 * {@link #removeOnTabSelectedListener(OnTabSelectedListener)}.
 */
@Deprecated
public void setOnTabSelectedListener(@Nullable OnTabSelectedListener listener) { ... }

/**
 * Callback interface invoked when a tab's selection state changes.
 */
public interface OnTabSelectedListener { ... }

I'm running in Genymotion with Samsung Galaxy S8 - API 26 - 1440x2960.

I'm not sure if there's an issue with the design:28.0.0 library or maybe I'm just doing something wrong in the build. It seems to work OK with earlier versions. Any advice is appreciated.

Upvotes: 2

Views: 3644

Answers (3)

guipivoto
guipivoto

Reputation: 18677

I downloaded the AAR file from both versions: 27.1.1 and 28.0.0:

Decompiling the TabLayout.class from both packages, I could see its signature has changed from:

27.1.1

@Deprecated
public void setOnTabSelectedListener(@Nullable TabLayout.BaseOnTabSelectedListener listener)
}

28.0.0

@Deprecated
public void setOnTabSelectedListener(@Nullable TabLayout.OnTabSelectedListener listener) {
}

So, now, that method is expecting a BaseOnTabSelectedListener and not OnTabSelectedListener

The old onTabSelectedListener does not implements the new BaseOnTabSelectedListener

So, probably have to import the material component as well which have the new implementation of OnTabSelectedListener:

implementation 'com.google.android.material:material:1.0.0'

Doc of old onTabSelectedListener (does not implements BaseOnTabSelectedListener

Doc of new onTabSelectedListener (implements BaseOnTabSelectedListener).

Sorry but I did not directly show how to fix it because I'm not able to go further right now. But that is the root cause I guess.

Upvotes: 4

Pedro Massango
Pedro Massango

Reputation: 5015

You should use the new Material Components dependencies. With this one everything works fine and you just need to add one line in Gradle to import all design components.

implementation 'com.google.android.material:material:1.0.0'

With this one line dependency RecyclerView, CardView, TabLayout, and all of view components come available. You also will have Chips, CardView, RecyclerView, tec.

Remember that:

You should not use the com.android.support and com.google.android.material dependencies in your app at the same time

Check it here about how to setup: https://medium.com/nyc-design/material-design-components-setup-on-android-studio-3-2-8b3194d9bebf

Upvotes: 0

ʍѳђઽ૯ท
ʍѳђઽ૯ท

Reputation: 16976

/**
 * @deprecated Use {@link #addOnTabSelectedListener(OnTabSelectedListener)} and
 * {@link #removeOnTabSelectedListener(OnTabSelectedListener)}.
 */

It is-was depreciated in API level 26.1.0 perhaps that's why you get this error.

To fix that, use addOnTabSelectedListener instead of setOnTabSelectedListener

Refer to this answer.

Example code:

tablayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tablayout));

As a note, don't use depreciated methods.

Upvotes: 1

Related Questions