Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot get CustomURLPrimaryDrawerItem to show up in miniDrawer #2620

Closed
6 tasks done
Eliasdevlb opened this issue Jun 14, 2020 · 17 comments
Closed
6 tasks done

Cannot get CustomURLPrimaryDrawerItem to show up in miniDrawer #2620

Eliasdevlb opened this issue Jun 14, 2020 · 17 comments

Comments

@Eliasdevlb
Copy link

Eliasdevlb commented Jun 14, 2020

About this issue

  • CustomUrlPrimaryDrawerItem does not work with the minidrawer
    I implemented the CustomUrlPrimaryDrawerItem methods but the item does not show with the icon, only the name is visible in the mini Drawer when I try to create an item with an icon from a URL, I even tried the URL for an icon that was with the sample https://avatars3.githubusercontent.com/u/1476232?v=3&s=460 and that still didn't work. I also tried doing this with the miniDrawer in the sample app and that did not work either.
    Thanks for all your hard work. I appreciate how fantastic this library is.

Details

  • [6.1.2 java/AndroidX] Used library version
  • [3.4.1] Used tooling / Android Studio version

Checklist

@mikepenz
Copy link
Owner

@R01NDev the MiniDrawer has its own item which also would not do url loading out of the box.

Similarly the mini drawer would also need a custom item to follow different behavior:
#2114 (comment)

Possibly I may can look into providing url loading out of the box again. but I'd need to think more about it first

@Eliasdevlb
Copy link
Author

What would be the best the quickest way to solve this issue, do I need to fork the library and makes changes to the minidrawer?

@mikepenz
Copy link
Owner

Oh the quickest would be:

0.) Create your custom mini drawer item
1.) Overwrite the MiniDrawerSliderView
2.) Adjust the generateMiniDrawerItem and getMiniDrawerType to understand your custom
item (https://github.com/mikepenz/MaterialDrawer/blob/develop/library/src/main/java/com/mikepenz/materialdrawer/widget/MiniDrawerSliderView.kt#L368-L391)
3.) Use the CustomMiniDrawerSliderView

@Eliasdevlb
Copy link
Author

The MiniDrawerSliderView class does not seem to exist in the 6.1.2 androidx version of the library

@mikepenz
Copy link
Owner

Oh for 6.1.2 you can do the same steps but for the MiniDrawer class instead :)

@Eliasdevlb
Copy link
Author

I have Created the CustomMiniDrawerItem as follows

public class CustomMiniDrawerItem extends BaseDrawerItem<CustomMiniDrawerItem, CustomMiniDrawerItem.ViewHolder> {
    private StringHolder mBadge;
    private BadgeStyle mBadgeStyle = new BadgeStyle();

    private boolean mEnableSelectedBackground = false;
    protected DimenHolder mCustomHeight;

    public CustomMiniDrawerItem() {

    }

    public CustomMiniDrawerItem(CustomUrlPrimaryDrawerItem customUrlPrimaryDrawerItem) {
        this.mIdentifier = customUrlPrimaryDrawerItem.mIdentifier;
        this.mTag = customUrlPrimaryDrawerItem.mTag;

        this.mBadge = null;
        this.mBadgeStyle = null;

        this.mEnabled = customUrlPrimaryDrawerItem.mEnabled;
        this.mSelectable = customUrlPrimaryDrawerItem.mSelectable;
        this.mSelected = customUrlPrimaryDrawerItem.mSelected;

        this.icon = customUrlPrimaryDrawerItem.icon;
        this.selectedIcon = customUrlPrimaryDrawerItem.selectedIcon;

        this.iconTinted = customUrlPrimaryDrawerItem.iconTinted;
        this.selectedColor = customUrlPrimaryDrawerItem.selectedColor;

        this.iconColor = customUrlPrimaryDrawerItem.iconColor;
        this.selectedIconColor = customUrlPrimaryDrawerItem.selectedIconColor;
        this.disabledIconColor = customUrlPrimaryDrawerItem.disabledIconColor;
    }
    
    public CustomMiniDrawerItem(PrimaryDrawerItem primaryDrawerItem) {
        this.mIdentifier = primaryDrawerItem.mIdentifier;
        this.mTag = primaryDrawerItem.mTag;

        this.mBadge = primaryDrawerItem.mBadge;
        this.mBadgeStyle = primaryDrawerItem.mBadgeStyle;

        this.mEnabled = primaryDrawerItem.mEnabled;
        this.mSelectable = primaryDrawerItem.mSelectable;
        this.mSelected = primaryDrawerItem.mSelected;

        this.icon = primaryDrawerItem.icon;
        this.selectedIcon = primaryDrawerItem.selectedIcon;

        this.iconTinted = primaryDrawerItem.iconTinted;
        this.selectedColor = primaryDrawerItem.selectedColor;

        this.iconColor = primaryDrawerItem.iconColor;
        this.selectedIconColor = primaryDrawerItem.selectedIconColor;
        this.disabledIconColor = primaryDrawerItem.disabledIconColor;
    }

    public CustomMiniDrawerItem(SecondaryDrawerItem secondaryDrawerItem) {
        this.mIdentifier = secondaryDrawerItem.mIdentifier;
        this.mTag = secondaryDrawerItem.mTag;

        this.mBadge = secondaryDrawerItem.mBadge;
        this.mBadgeStyle = secondaryDrawerItem.mBadgeStyle;

        this.mEnabled = secondaryDrawerItem.mEnabled;
        this.mSelectable = secondaryDrawerItem.mSelectable;
        this.mSelected = secondaryDrawerItem.mSelected;

        this.icon = secondaryDrawerItem.icon;
        this.selectedIcon = secondaryDrawerItem.selectedIcon;

        this.iconTinted = secondaryDrawerItem.iconTinted;
        this.selectedColor = secondaryDrawerItem.selectedColor;

        this.iconColor = secondaryDrawerItem.iconColor;
        this.selectedIconColor = secondaryDrawerItem.selectedIconColor;
        this.disabledIconColor = secondaryDrawerItem.disabledIconColor;
    }

    
    public CustomMiniDrawerItem withCustomHeightRes(@DimenRes int customHeightRes) {
        this.mCustomHeight = DimenHolder.fromResource(customHeightRes);
        return this;
    }

    public CustomMiniDrawerItem withCustomHeightDp(int customHeightDp) {
        this.mCustomHeight = DimenHolder.fromDp(customHeightDp);
        return this;
    }

    public CustomMiniDrawerItem withCustomHeightPx(int customHeightPx) {
        this.mCustomHeight = DimenHolder.fromPixel(customHeightPx);
        return this;
    }

    public CustomMiniDrawerItem withCustomHeight(DimenHolder customHeight) {
        this.mCustomHeight = customHeight;
        return this;
    }

    public CustomMiniDrawerItem withEnableSelectedBackground(boolean enableSelectedBackground) {
        this.mEnableSelectedBackground = enableSelectedBackground;
        return this;
    }

    @Override
    public int getType() {
        return R.id.material_drawer_item_mini;
    }

    @Override
    @LayoutRes
    public int getLayoutRes() {
        return R.layout.material_drawer_item_mini;
    }

    @Override
    public void bindView(CustomMiniDrawerItem.ViewHolder viewHolder, List payloads) {
        super.bindView(viewHolder, payloads);

        Context ctx = viewHolder.itemView.getContext();

        //set a different height for this item
        if (mCustomHeight != null) {
            RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) viewHolder.itemView.getLayoutParams();
            lp.height = mCustomHeight.asPixel(ctx);
            viewHolder.itemView.setLayoutParams(lp);
        }

        //set the identifier from the drawerItem here. It can be used to run tests
        viewHolder.itemView.setId(hashCode());

        //set the item enabled if it is
        viewHolder.itemView.setEnabled(isEnabled());

        //set the item selected if it is
        viewHolder.itemView.setSelected(isSelected());

        //
        viewHolder.itemView.setTag(this);

        //get the correct color for the icon
        int iconColor = getIconColor(ctx);
        int selectedIconColor = getSelectedIconColor(ctx);

        if (mEnableSelectedBackground) {
            //get the correct color for the background
            int selectedColor = getSelectedColor(ctx);
            //set the background for the item
            themeDrawerItem(ctx, viewHolder.view, selectedColor, isSelectedBackgroundAnimated());
        }

        //set the text for the badge or hide
        boolean badgeVisible = StringHolder.applyToOrHide(mBadge, viewHolder.badge);
        //style the badge if it is visible
        if (badgeVisible) {
            mBadgeStyle.style(viewHolder.badge);
        }

        //get the drawables for our icon and set it
        Drawable icon = ImageHolder.decideIcon(getIcon(), ctx, iconColor, isIconTinted(), 1);
        Drawable selectedIcon = ImageHolder.decideIcon(getSelectedIcon(), ctx, selectedIconColor, isIconTinted(), 1);
        ImageHolder.applyMultiIconTo(icon, iconColor, selectedIcon, selectedIconColor, isIconTinted(), viewHolder.icon);

        //for android API 17 --> Padding not applied via xml
        int verticalPadding = ctx.getResources().getDimensionPixelSize(R.dimen.material_drawer_padding);
        int topBottomPadding = ctx.getResources().getDimensionPixelSize(R.dimen.material_mini_drawer_item_padding);
        viewHolder.itemView.setPadding(verticalPadding, topBottomPadding, verticalPadding, topBottomPadding);

        //call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
        onPostBindView(this, viewHolder.itemView);
    }

    @Override
    public CustomMiniDrawerItem.ViewHolder getViewHolder(View v) {
        return new CustomMiniDrawerItem.ViewHolder(v);
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        private View view;
        private ImageView icon;
        private TextView badge;

        public ViewHolder(View view) {
            super(view);

            this.view = view;
            this.icon = (ImageView) view.findViewById(R.id.material_drawer_icon);
            this.badge = (TextView) view.findViewById(R.id.material_drawer_badge);
        }
    }
}

And then I created the CustomMiniDrawer

public class CustomMiniDrawer extends MiniDrawer {
    private boolean mEnableProfileClick = true;
    private boolean mEnableSelectedMiniDrawerItemBackground = false;

    @Override
    public int getMiniDrawerType(IDrawerItem drawerItem) {
        if (drawerItem instanceof CustomMiniDrawerItem) {
            return ITEM;
        }
        return -1;
    }

    private boolean mIncludeSecondaryDrawerItems = false;
    public CustomMiniDrawer withIncludeSecondaryDrawerItems(boolean includeSecondaryDrawerItems) {
        this.mIncludeSecondaryDrawerItems = includeSecondaryDrawerItems;
        return this;
    }

    @Override
    public IDrawerItem generateMiniDrawerItem(IDrawerItem drawerItem) {
        if (drawerItem instanceof CustomUrlPrimaryDrawerItem) {
            return mIncludeSecondaryDrawerItems ? new CustomMiniDrawerItem((CustomUrlPrimaryDrawerItem) drawerItem).withEnableSelectedBackground(mEnableSelectedMiniDrawerItemBackground) : null;
        }
        return null;
    }
}

And then I Changed the MiniDrawerActivity's onCreate as follows

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mini_drawer);

        // Handle Toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        //set the back arrow in the toolbar
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setTitle(R.string.drawer_item_mini_drawer);

        // Create a few sample profile
        // NOTE you have to define the loader logic too. See the CustomApplication for more details
        // Create the AccountHeader
        result = new DrawerBuilder()
                .withActivity(this)
                .withToolbar(toolbar)
                .withTranslucentStatusBar(false)
                .withAccountHeader(headerResult) //set the AccountHeader we created earlier for the header
                .addDrawerItems(
                        new CustomMiniDrawerItem().withName("Test1").withIcon(new ImageHolder("https://avatars3.githubusercontent.com/u/1476232?v=3&s=460"))
                ) // add the items we want to use with our Drawer
                .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                    @Override
                    public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                        if (drawerItem instanceof Nameable) {
                            Toast.makeText(MiniDrawerActivity.this, ((Nameable) drawerItem).getName().getText(MiniDrawerActivity.this), Toast.LENGTH_SHORT).show();
                        }
                        return false;
                    }
                })
                .withGenerateMiniDrawer(true)
                .withSavedInstance(savedInstanceState)
                // build only the view of the Drawer (don't inflate it automatically in our layout which is done with .build())
                .buildView();

        //the MiniDrawer is managed by the Drawer and we just get it to hook it into the Crossfader
        miniResult = (CustomMiniDrawer) result.getCustomMiniDrawer();

        //get the widths in px for the first and second panel
        int firstWidth = (int) UIUtils.convertDpToPixel(300, this);
        int secondWidth = (int) UIUtils.convertDpToPixel(72, this);

        //create and build our crossfader (see the MiniDrawer is also builded in here, as the build method returns the view to be used in the crossfader)
        //the crossfader library can be found here: https://github.com/mikepenz/Crossfader
        crossFader = new Crossfader()
                .withContent(findViewById(R.id.crossfade_content))
                .withFirst(result.getSlider(), firstWidth)
                .withSecond(miniResult.build(this), secondWidth)
                .withSavedInstance(savedInstanceState)
                .build();

        //define the crossfader to be used with the miniDrawer. This is required to be able to automatically toggle open / close
        miniResult.withCrossFader(new CrossfadeWrapper(crossFader));

        //define a shadow (this is only for normal LTR layouts if you have a RTL app you need to define the other one
        crossFader.getCrossFadeSlidingPaneLayout().setShadowResourceLeft(R.drawable.material_drawer_shadow_left);
    }

but Still no dice, I can only see the icon + element only when the menu is expanded. Am I missing something?

@mikepenz
Copy link
Owner

@R01NDev seems you may mix up the items.

So your Drawer still wants to be created with the CustomUrlPrimaryDrawerItem items.

And the MiniDrawer will then get this CustomUrlPrimaryDrawerItem and construct a CustomMiniDrawerItem to be displayed in the small drawer.

@Eliasdevlb
Copy link
Author

I have changed up the onCreate function according to your previous reply

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mini_drawer);

        // Handle Toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        //set the back arrow in the toolbar
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setTitle(R.string.drawer_item_mini_drawer);

        // Create a few sample profile
        // NOTE you have to define the loader logic too. See the CustomApplication for more details
        // Create the AccountHeader
        result = new DrawerBuilder()
                .withActivity(this)
                .withToolbar(toolbar)
                .withTranslucentStatusBar(false)
                .withAccountHeader(headerResult) //set the AccountHeader we created earlier for the header
                .addDrawerItems(
                        new CustomUrlPrimaryDrawerItem().withName("Test1").withIcon("https://avatars3.githubusercontent.com/u/1476232?v=3&s=460"),
                        new CustomUrlPrimaryDrawerItem().withName("Test1").withIcon(new ImageHolder("https://avatars3.githubusercontent.com/u/1476232?v=3&s=460"))

                ) // add the items we want to use with our Drawer
                .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                    @Override
                    public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                        if (drawerItem instanceof Nameable) {
                            Toast.makeText(MiniDrawerActivity.this, ((Nameable) drawerItem).getName().getText(MiniDrawerActivity.this), Toast.LENGTH_SHORT).show();
                        }
                        return false;
                    }
                })
                .withGenerateMiniDrawer(true)
                .withSavedInstance(savedInstanceState)
                // build only the view of the Drawer (don't inflate it automatically in our layout which is done with .build())
                .buildView();

        //the MiniDrawer is managed by the Drawer and we just get it to hook it into the Crossfader
        miniResult = (CustomMiniDrawer) result.getCustomMiniDrawer();


        //get the widths in px for the first and second panel
        int firstWidth = (int) UIUtils.convertDpToPixel(300, this);
        int secondWidth = (int) UIUtils.convertDpToPixel(72, this);

        //create and build our crossfader (see the MiniDrawer is also builded in here, as the build method returns the view to be used in the crossfader)
        //the crossfader library can be found here: https://github.com/mikepenz/Crossfader
        crossFader = new Crossfader()
                .withContent(findViewById(R.id.crossfade_content))
                .withFirst(result.getSlider(), firstWidth)
                .withSecond(miniResult.build(this), secondWidth)
                .withSavedInstance(savedInstanceState)
                .build();

        //define the crossfader to be used with the miniDrawer. This is required to be able to automatically toggle open / close
        miniResult.withCrossFader(new CrossfadeWrapper(crossFader));

        //define a shadow (this is only for normal LTR layouts if you have a RTL app you need to define the other one
        crossFader.getCrossFadeSlidingPaneLayout().setShadowResourceLeft(R.drawable.material_drawer_shadow_left);
    }

    private OnCheckedChangeListener onCheckedChangeListener = new OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(IDrawerItem drawerItem, CompoundButton buttonView, boolean isChecked) {
            if (drawerItem instanceof Nameable) {
                Log.i("material-drawer", "DrawerItem: " + ((Nameable) drawerItem).getName() + " - toggleChecked: " + isChecked);
            } else {
                Log.i("material-drawer", "toggleChecked: " + isChecked);
            }
        }
    };

I have added some debug calls in the CustomMiniDrawerItem class to check if there's an attempt to create the item and there are but I still cannot see the item. I am not sure why that would be.

@mikepenz
Copy link
Owner

(A side question. what's the main reason to use v6.x compared to v8? If I add url support to the default items it would only be on the latest version)

I would need to give it a closer look. Not sure if it is a possibility that you send the relevant app (with other parts removed) as a sample via e-mail so I can compile and run it myself?

@Eliasdevlb
Copy link
Author

Eliasdevlb commented Jun 15, 2020

so our main app is running on AndroidX and we do not have a Kotlin version. I understand that it's not required to run 8.x which is written in Kotlin but I could not get any reference of the minidrawer to instantiate on 8.x so I ended up looking at the 6.1.2 version which was written in Java and even then I had to spend a couple of hours fixing gradle dependencies and moving over the "library" in the sample app. Unfortunately I cannot send a sample of the app but I can send the changes I made to the example app if that helps. Also curious if you want to make the changes to the 8.x when would that be done because I can Probably port your work over to the 6.1.2 version or just try to get 8.x working again.

@mikepenz
Copy link
Owner

I would have to give it a look over the weekend in regards to adding it. I refrained to do so for the longest time as it would have addd some code and I wanted to keep it minimal but v8 should offer the flexibility to now add it more flexibly.

I do believe back porting would be quite some effort as the version differ significantly.

Let's see

@Eliasdevlb
Copy link
Author

Eliasdevlb commented Jun 15, 2020

Thanks for all the effort you put in to this, I appreciate your patience and your quick replies. Is there anything I can do with 6.1.2 to get this going even in some hacky ways I have a deadline 2 days from now to showcase a demo, I know this isn't your problem but I just wanted to be sure that the issue is not the classes that I wrote above and it's something that goes further into the library's core.

@mikepenz
Copy link
Owner

@R01NDev if you can create a super minimal sample or do the adjustments you did on the sample app from v6.1.2 then I can have a look at the code and debug on why it may not behave for you.

I definitely works as it has been done before. but flying over the code quick here in the comments I most likely miss out on something

@Eliasdevlb
Copy link
Author

Eliasdevlb commented Jun 15, 2020

I've uploaded the example app with the changes that I made /downloaded/

@mikepenz
Copy link
Owner

Ok I have done a small update to v6.1.3 so you can achieve this without modifying core drawer code.

Here is a fully working sample:
md6.1.3_UrlLoadingMiniDrawer.zip

@Eliasdevlb
Copy link
Author

Eliasdevlb commented Jun 15, 2020

This is fantastic, thank you so much for all the work you've done for this library and for all the help.

@mikepenz
Copy link
Owner

You are very welcome 😄.

And thank you so much for the support! Really really appreciated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants