Issue when changing from support library v7 to androidx
Closed this issue · 10 comments
My settings page looked like that before.
Now it's looking like that.
This is API 16 Old phone
Manifest
<activity
android:name=".frontend.settings.SettingsActivity"
android:label="@string/settings"
android:screenOrientation="portrait"
android:theme="@style/SettingsTheme">
</activity>
I am using this Theme:
<style name="SettingsTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorPrimary</item>
<item name="android:textColorPrimary">@android:color/black</item>
<item name="android:textColorSecondary">@color/grey</item>
</style>
I am importing these libraries:
implementation 'androidx.preference:preference:1.0.0'
implementation 'com.takisoft.preferencex:preferencex:1.0.0'
pref_notification.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.preference.PreferenceCategory
android:key=""
android:layout="@layout/preferences_notif_title"
android:title="@string/notif_title_business_related" />
<androidx.preference.PreferenceCategory
android:key="title_email_job"
android:layout="@layout/preferences_category"
android:title="@string/notif_title_email_job">
<androidx.preference.SwitchPreferenceCompat
android:key="email-pro-request-new"
android:title="@string/notif_email_new_customer_requests" />
<androidx.preference.SwitchPreferenceCompat
android:key="email-pro-request-reminder"
android:title="@string/notif_email_request_reminders" />
<androidx.preference.SwitchPreferenceCompat
android:key="email-pro-bid-activity"
android:summary="@string/notif_email_new_customer_activity_summary"
android:title="@string/notif_email_new_customer_activity" />
<androidx.preference.SwitchPreferenceCompat
android:key="email-pro-bid-view"
android:title="@string/notif_email_customer_viewing_bids" />
<androidx.preference.SwitchPreferenceCompat
android:key="email-pro-bid-other"
android:summary="@string/notif_email_other_bid_activity_summary"
android:title="@string/notif_email_other_bid_activity" />
<androidx.preference.SwitchPreferenceCompat
android:key="email-pro-profile-reminder"
android:title="@string/notif_email_profile_setup_reminder" />
<androidx.preference.SwitchPreferenceCompat
android:key="email-pro-bm-budget-alert"
android:title="@string/notif_email_bidmatch_budget_alert" />
<androidx.preference.SwitchPreferenceCompat
android:key="email-pro-bm-reminder"
android:title="@string/notif_email_bidMatch_setup_reminder" />
<androidx.preference.SwitchPreferenceCompat
android:key="email-pro-account-activity"
android:title="@string/notif_email_account_activity" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key="title_push"
android:layout="@layout/preferences_category"
android:title="@string/notif_title_get_push_notif_when">
<androidx.preference.SwitchPreferenceCompat
android:key="push-pro-request-new"
android:title="@string/notif_push_new_customer_requests" />
<androidx.preference.SwitchPreferenceCompat
android:key="push-pro-bid-activity"
android:summary="@string/notif_push_new_customer_activity_summary"
android:title="@string/notif_push_new_customer_activity" />
<androidx.preference.SwitchPreferenceCompat
android:key="push-pro-bid-view"
android:title="@string/notif_push_customer_viewing_bids" />
<androidx.preference.SwitchPreferenceCompat
android:key="push-pro-bid-follow-up"
android:title="@string/notif_push_bid_follow_up" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key="title_email_me_with"
android:layout="@layout/preferences_category"
android:title="@string/notification_title_email_me_with">
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-pro-tips"
android:summary="@string/notif_with_tips_success_summary"
android:title="@string/notif_with_tips_success" />
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-pro-newsletter"
android:summary="@string/notif_with_announcements_summary"
android:title="@string/notif_with_announcements" />
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-pro-feedback"
android:summary="@string/notif_with_help_bidvine_summary"
android:title="@string/notif_with_help_bidvine" />
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-pro-offers"
android:summary="@string/notif_with_discount_offers_summary"
android:title="@string/notif_with_discount_offers" />
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-pro-insights"
android:summary="@string/notif_with_market_report_summary"
android:title="@string/notif_with_market_report" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key=""
android:layout="@layout/preferences_notif_title"
android:title="@string/notif_title_customer_related" />
<androidx.preference.PreferenceCategory
android:key="title_email_about_job_requests"
android:layout="@layout/preferences_category"
android:title="@string/notif_title_emails_about_job_requests">
<androidx.preference.SwitchPreferenceCompat
android:key="email-cust-request-activity"
android:summary="@string/notif_pros_send_you_bids"
android:title="@string/notif_request_activity" />
<androidx.preference.SwitchPreferenceCompat
android:key="email-cust-request-reminder"
android:summary="@string/notif_you_have_upcoming_projects"
android:title="@string/notif_job_reminders_and_updates" />
<androidx.preference.SwitchPreferenceCompat
android:key="email-cust-review"
android:summary="@string/notif_you_review_pros_you_hired"
android:title="@string/notif_reviews" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key="title_get_push_notifications"
android:layout="@layout/preferences_category"
android:title="@string/notif_title_get_push_notif_when">
<androidx.preference.SwitchPreferenceCompat
android:key="push-cust"
android:title="@string/notif_all_push_notif" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key=""
android:layout="@layout/preferences_category"
android:title="@string/notif_title_text_me_about">
<androidx.preference.SwitchPreferenceCompat
android:key="sms-cust"
android:title="@string/notif_all_text_notif" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key="title_email_me_about"
android:layout="@layout/preferences_category"
android:title="@string/notif_title_email_me_about">
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-cust-tips"
android:summary="@string/notif_helpful_tips_inspiration_summary"
android:title="@string/notif_helpful_tips_inspiration" />
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-cust-recommendations"
android:summary="@string/notif_recommendations_summary"
android:title="@string/notif_recommendations" />
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-cust-offers"
android:summary="@string/notif_special_offers_summary"
android:title="@string/notif_special_offers" />
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-cust-feedback"
android:summary="@string/notif_invitations_give_feedback_summary"
android:title="@string/notif_invitations_give_feedback" />
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-cust-reminders"
android:summary="@string/notif_reminders_summary"
android:title="@string/notif_reminders" />
<androidx.preference.SwitchPreferenceCompat
android:key="marketing-cust-other"
android:summary="@string/notif_other_summary"
android:title="@string/notif_other" />
</androidx.preference.PreferenceCategory>
</androidx.preference.PreferenceScreen>
I'm extending from PreferenceFragmentCompat
calling this method as mentioned.
@Override
public void onCreatePreferencesFix(Bundle savedInstanceState, String rootKey) {
// Select between Provider preferences or Full preferences(Provider + customer)
User user = Preferences.getUserModel();
if (user != null) {
String count = user.getPreviousRequestsCount();
if (!TextUtils.isEmpty(count) && !count.equals("0")) {
setPreferencesFromResource(R.xml.pref_notification_full, rootKey);
return;
}
}
setPreferencesFromResource(R.xml.pref_notification_pro, rootKey);
}
There are two problems with your XML:
- Do not use fully qualified class names (e.g.
androidx.preference.PreferenceCategory
) because the lib overrides some of the preferences by defining the same class and prefixing it with the appropriate package name. The solution is simple: just removeandroidx.preference.
everywhere. - The new design language says that categories should have lines between them (hence the line after the first element). You can either remove that first empty category (and make the title of it the title of the toolbar instead) or use a hidden API (see #111) to tell the lib not to render the line below the first element by adding the attribute
app:allowDividerBelow="false"
to the first category.
@Gericop Now that I removed the androidx.preference.
from the XML. I am receiving the old error back: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getPaddingStart()' on a null object reference
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getPaddingStart()' on a null object reference
at androidx.core.view.ViewCompat.getPaddingStart(ViewCompat.java:1527)
at com.takisoft.preferencex.PreferenceCategory.onBindViewHolder(PreferenceCategory.java:146)
at androidx.preference.PreferenceGroupAdapter.onBindViewHolder(PreferenceGroupAdapter.java:381)
at androidx.preference.PreferenceGroupAdapter.onBindViewHolder(PreferenceGroupAdapter.java:45)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3641)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4194)
at android.view.View.layout(View.java:16784)
at android.view.ViewGroup.layout(ViewGroup.java:5333)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:16784)
at android.view.ViewGroup.layout(ViewGroup.java:5333)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1702)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1556)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1465)
at android.view.View.layout(View.java:16784)
at android.view.ViewGroup.layout(ViewGroup.java:5333)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:16784)
at android.view.ViewGroup.layout(ViewGroup.java:5333)
at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:444)
at android.view.View.layout(View.java:16784)
at android.view.ViewGroup.layout(ViewGroup.java:5333)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:16784)
at android.view.ViewGroup.layout(ViewGroup.java:5333)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1702)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1556)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1465)
at android.view.View.layout(View.java:16784)
at android.view.ViewGroup.layout(ViewGroup.java:5333)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:16784)
at android.view.ViewGroup.layout(ViewGroup.java:5333)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2370)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2079)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1230)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6731)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:777)
at android.view.Choreographer.doCallbacks(Choreographe
Okay, I see the problem. In your custom layout, you set for the PreferenceCategory
, there's no parent of the TextView
(id=@android:id/title
). For the time being, make sure there's a parent view for the TextView
(or just stop using the custom layout, it looks weird to me).
@Gericop, the left padding was solved when I added app:iconSpaceReserved="false"
in the Switches. The link that you sent me helped me a lot (https://stackoverflow.com/questions/51518758/preferencefragmentcompat-has-padding-on-preferencecategory-that-i-cant-get-rid). However, it only works for API 21 and above.
When I test with API 16, the paddings still have problems and your fix now doesn't make difference. If I remove the library, the issue continues the same.
I don't understand why the divider moved to the PreferenceCategory and not between the items as it was before.
I saw that the new material design guideline shows the divider between groups and not items. So, if I follow the new guideline, my problem is this extra header title that I have in my app. I need to find a way to remove the divider from them. Because I am adding an extra PreferenceCategory
between some groups.
@andreluizreis Like is said before, the divider can be removed: use a hidden API (see #111) to tell the lib not to render the line below the first element by adding the attribute app:allowDividerBelow="false"
to the first category.
Also, I did not send you that link. The solution is to not use fully qualified names (e.g. androidx.preference.PreferenceCategory
) but the class name alone (e.g. PreferenceCategory
) and specify app:iconSpaceReserved="false"
for the category as well. Note that you might need to update your custom category layout so that the title TextView
will be inside a parent view.
@Gericop I did all the modifications that you advised me. It's working most of the screens now. However, the only downside is that to use SwitchPreferenceCompat
, I need to keep androidx.preference.PreferenceScreen
. If I remove androidx.preference
, I will receive an error element is not allowed here
. Right now, only API 16 with small screens the padding is wrong. I will try to fix that change the dimensions of padding dynamically.
@andreluizreis That is just a lint error, you can ignore it.
@Gericop, Thanks for helping me solve this problem these days. I will keep my design like the image below. I removed the header titles and I split into two different fragments. Now, I don't have more problems with the dividers.
We can close this issue now. I really appreciate the attention that you gave me. I wish you the best.
@andreluizreis You can also use nested PreferenceScreen
s to show the fine-grained settings on separate pages. Check out the sample app for details.