How to modify/adapt methods from API library? - java

I'm using Big Nerd Ranch's recyclerview-multiselect library to give my RecyclerView's CardViews a multi-selection capability. I've worked out my app-specific kinks for the most part, but I ran into a pretty big issue. Whenever the RecyclerView is in SelectionMode and has to recreate a card (which is often, because that's practically the point of RecyclerView, at least if I understand it correctly,) it throws this error:
java.lang.ClassCastException: android.graphics.drawable.StateListDrawable cannot be cast to android.support.v7.widget.RoundRectDrawableWithShadow
at android.support.v7.widget.CardViewEclairMr1.getShadowBackground(CardViewEclairMr1.java:159)
at android.support.v7.widget.CardViewEclairMr1.getMinWidth(CardViewEclairMr1.java:150)
at android.support.v7.widget.CardView.onMeasure(CardView.java:181)
at android.view.View.measure(View.java:16498)
Logically, I followed the error to whatever source was causing a StateListDrawable to be set as the CardView's background. What I found was summed up by a commented section in this class. It reads as follows:
selectionModeBackgroundDrawable defaults to a StateListDrawable that displays your colorAccent theme color when state_activated=true, and nothing otherwise.
In the SwappingHolder class, you can see where the StateListDrawable, causing the error, is being returned. Also, if you look in the CardViewEclairMr1.java, as suggested in the error, you can see the method that most directly causes the error:
private RoundRectDrawableWithShadow getShadowBackground(CardViewDelegate cardView) {
return ((RoundRectDrawableWithShadow) cardView.getBackground());
}
To be honest, after all this snooping around in the BigNerdRanch library, I'm still not sure what to do! I was thinking I might need to #Override the BigNerdRanch methodology which brings in a StateListDrawable, but that would be getting my hands so dirty with the library, it would defeat the purpose of implementing their API to begin with. How do I fix this error?

A little late with the answer but here is something that I found and that worked for me.
Check to see if your CardView layout is wrapped inside a ViewGroup and if is not that might be the problem.
SwappingHolder works by swapping out the drawables of the top-level View. CardView uses its own drawables, so it will not work if you use it as the top-level View.
So the right way is this
<FrameLayout
...
>
<CardView
...
>
</CardView>
</FrameLayout>
Or you can implement the SelectableHolder interface yourself, and choose how you want to display a selected item.
All these are the authors words so here is a [link to GitHub][link] to the actual page
[link]:https://github.com/bignerdranch/recyclerview-multiselect/issues/14.
Good luck !

Related

How to construct the RecyclerView for the following UI vertically?

The expected UI for my application should look like this:
I have thought about using a view pager but I cannot figure out how to change opacity of the next items or make the item in view to be centered and be elastic.
I have researched multiple open source GitHub repos and found two which seems similar to what I have approaching to do.
https://github.com/bloderxd/deck
https://github.com/Ramotion/garland-view-android
I do not know how to solve the problem of opacity or going to the next item using the next button in the UI (which was designed by me for a project).
So far, I could only create a simple XML representation of the UI without the view pager but I do not know what other libraries and views I need to implement to make it interactive and elastic like in the UI.
My request is how I could build the application level code for this UI. If there is any other obscurities in my questioning, feel free to comment and reach out because I am relatively new to this kind of development. Thank you.

RecyclerView with swipe action menu

I have a RecyclerView with the implementation of ItemTouchHelper. I am dragging and sorting the items in RecyclerView using ItemTouchHelper.
Also I am performing different actions on different direction of swipe. If user goes from left to right (Swipe) I just Deactivate status of item. If he perform right to left swipe I activate the relevant item.
What I want:
But now here comes the change, What I want is that I need to show some icons after I perform right or left swipe. And By clicking on those icons/buttons I want to perform action then.
Problem:
Problem is as I told you I have implementation of ItemTouchHelper, then how I am doing to perform what I wanted (as described above)
How to solve this? I have seen many libraries but they have limitations, also as the app has very much things going and there are some more implementations on RecyclerView used in our app, so I really do not want to risk the rest of implementations for the sake of this..
UPDATE 1:
To clear my question more I am going to add on more. Right now My implementation is something like this. But this is not what I want. I want to show swipe menu for any type of swipe I mean either it is left or right I want to show some icons on left and right side of item
You can take iOS swipe menu as an example (see here). I want exactly same behavior in android.
You're asking the impossible: suggest a library that doesn't exist (as you have already found out).
You're asking people to also find a solution for a problem you only briefly describe. You're not providing any code whatsoever, nor any specific issue you're facing when trying to come up with a solution; you're essentially expecting magic to happen.
How can you make this better?
Provide something like: "I'm attempting to implement a swipe solution for a recycler view's row; when I try to do YYYY is happening instead. Hhere's my piece of code where I do , calculated like this , am I missing something?"
Anyway...
You claim to be using an ItemTouchHelper already, so, if you look at how a very basic one works, you'll notice that the helper will ultimately draw on the canvas directly via:
#Override
public void onChildDraw(
final Canvas canvas,
final RecyclerView recyclerView,
final RecyclerView.ViewHolder viewHolder,
final float deltaX,
final float deltaY,
final int actionState,
final boolean isCurrentlyActive) {
This is derived from the platform ItemTouchHelper.SimpleCallback. So...
If you want to implement your solutions, you'll need to implement it there to do things like stop dragging, draw the content (icons), etc.
It's not a trivial solution and getting the whole thing right is difficult; more so if you introduce "some more implementations on RecyclerView".
I hope this answer points you in the right direction, and that your next related question is more about what you've tried (and failed) to do, than a "please do this for me" scenario. (If your intentions weren't those, please apologize, but you spent 5 minutes typing this question and it would take hours/days to implement this, so set your expectations this time).
Finally, when I wrote this, I realized most people wanted iOS swipe behavior; unfortunately, said behavior is not pre-implemented (like on iOS) on Android and you have to deal with it yourself; it's not impossible nor the most difficult task on earth to do on Android, but will give you a few headaches if you're hacking RecyclerView too much.
UPDATE
You've realized now, that ItemTouchHelper has a problem. It draws on the Canvas directly, so it has no knowledge of a Layout, View, Margin, etc. These are all things that live outside the realm of the touch helper. The helper is given a canvas, and drawing capabilities and that's it.
Where does this canvas size come from?
Well, it's calculated during the layout/measure pass(es) for the RecyclerView and its views.
How do I then stop dragging "at exactly the center of the screen" then?
Pass the values to your Helper; remember that the responsibility of calculating where the middle of the screen is, is not in the TouchHelper's contract; but your Activity/Fragment does know this. Provide the information the Touch Helper needs to perform the things you want it to perform.
Revert "back" to the original position, means knowledge of what the initial state was, etc. All this information is known by the RecyclerView and beyond, not the TouchHelper.
So you'd need to measure your layouts, save some values, pass them to the touchhelper so it can operate, etc.
As you can see, the full picture starts to become more and more complicated. My advice to you is:
Try to push this feature OUT as "the platform doesn't do it it will take time, it's not worth" (the worthiness and discoverability of swipe actions is dubious at best, but it's an ubiquitous action nowadays so you may have to do it regardless).
If you really have to do this, abstract things as much as you can, create all the classes/interfaces you think you can need, even if you end up with a "MiddleScreenCalculatorDelegate" kind of thing. It will be easier to fix later, but at least have each component do a very small subset of things.
Lastly, your item touch helper will have to calculate how much offset (delta) has the view been swiped already and stop when it reaches a known threshold.
Good luck :)
p.s.: I suggest you post a different question with specific issue(s) to get better help, this answer is very unhelpful as it is. :)

Viewpager with listviews

Has anybody had any luck with a view pager switching between fragments that contain listviews? In particular, the listviews I am working with inflate two separate layouts to get the desired effect. However, to my understanding this is causing the viewpager to disappear as well as the tabhost. I believe this to be so because it is working with other fragments that only inflate once.
Edit 1:
I was trying to see what would happen if I used one of the fragments that showed the tabhost and used the viewpager first. I would switch views and see the correct next one. However, shortly thereafter one of the fragments that does not show the tabhost or use the viewpager, for some odd reason, would load up.
Edit 2:
It's weird it is not even loading up on the right page. It should load up on 3 but instead it loads up on 2 and replaces the former screen that was actually supposed to be there.
Adding listviews to two fragments is very easy.
In short, you want to have a main activity that's the viewpager itself. Next, the viewpager is going to host two tabs (can be as many as you want, really) which will both contain separate layouts...each with a listview of its own.
Code
The first thing we need to do is add some classes. I've made a GitHub Gist of 4 classes that I'd like you to implement into your project. You'll need to change the package name and R class to meet your project's needs.
Gist: https://gist.github.com/Andrew-Quebe/b3e9f1d0f8223ba2f8df
Second, we need to make our host activity. This is what will show the tabs and toolbar. See this next Gist as I don't want to spam up this answer with tons of code.
Gist: https://gist.github.com/Andrew-Quebe/8add2fc064397ab8efe4
You've probably gotten an error in the MainActivity.java file due to a missing ViewPagerAdapter class. That's up next!
Gist: https://gist.github.com/Andrew-Quebe/fd70ee97c2e00d72f025
And finally, the tabs that'll show our listviews!
Gist: https://gist.github.com/Andrew-Quebe/3e2a87706c98a69e7353
My apologies for taking so long in my response...I actually took the time to build all this code and error check it for you. I had an example of tabs once before but it was outdated...you weren't the only reason I made all this code. The full project can be found on GitHub here: https://github.com/Andrew-Quebe/SlidingTabsExample
Hope this helps!
Edit:
Download the sample APK to see how everything looks: https://github.com/AMQTech/SlidingTabsExample/blob/master/APKs/Sample.apk?raw=true
First of all I would like to apologize. I pointed you all in the wrong way. I did some research and as it turns out you cannot have the fragment container (frame layout) in the activity layout already. All I had to do was put the fragment container into a different layout and inflate it when the time came to switch to another fragment class and that fixed it. Thanks to everyone.

LinearLayout to animate when shown

I have a vertical LinearLayout which has two another vertical layouts inside. The first one is always shown, and the second one depends on some event. I do want to animate that second layout when shown. How can I do it smoothly and nice? Thank you so much,
You should check out this library on Github. It may help. It is an animation library for listviews.
ListViewAnimations
A very simple, yet elegant way to get your layouts animated is by using the android:animateLayoutChanges="true" on its parent. This will likely take a lot of work in getting a nice animation out of your hands, unless you want to customize it.
With KitKat, Google introduced the android.transtion API, which may also be worth looking at.
You can create your own animation and you apply that animation to your layout when you need(In your case at the time of shown your layout)
yourLayout.startAnimation(yourAnimation);

android default xml layout not loading

I'm trying to make a ListActivity with check boxes using one of the built in android layouts, android.R.layout.simple_list_item_multiple_choice. For background, I'm fetching the list in a private AsyncTask, then calling the adapter like this:
listActivity.setListAdapter(new ArrayAdapter<String>(listActivity,
android.R.layout.simple_list_item_multiple_choice, mDisplayList));
However when I run my code, the ListView is displayed with list_item.xml, which I'm using for all the other ListViews in my project. Any idea why this is happening?
The reason the right xml layout wasn't being used was because my AsyncTask was extending my (other) custom AsyncTask that used another xml layout and I left in this line.
super.onPostExecute();
which was at the end of the method so the inherited layout trumped the one I wanted.
When you use the android R in this way: android.R.layout... than you already have the package android before the class name R.
If you explicitly provide a class name with a complete package name, you don't need to import it, too.
That's for the case that you have the same class name from different packages which happens often when you use the android.R and your generated R class.
You don't need to import android.R.layout since you invoke it explicitely using android.R.layout.simple_list_item_multiple_choice.
That post may be of use.
Update from comment
It's hard to figure out what's the problem. Did you try to clean your project and rebuild? Sometime android int id's just do strange things if you don't clean the project and regenerate the gen files. But messing android internal references is highly unlikely… If it doesn't work, you may have another polluting setListAdapter somewhere else but it's hard to say without your full project.

Categories