not sure if SO is the right place for this kind of question but here it goes.
I find it relatively hard to write clean code in Android. One problem I struggle with repeatedly are click events in GridView items. Say I have a complex layout (in a custom UI-element) that I inflate for each GridView item that contains multiple Buttons. A button click yields multiple events like database modifications, display of dialogs etc.
If I would handle click events inside those UI elements this would look like as follows:
Fragment -> GridViewAdapter -> MyGridViewItem -> OnClickButton1() -> modifyDB()
I don't want the MyGridViewItem to know about any DB modifications or stuff like that. Or in other words: I don't want to handle those events deep down in my code, but I'm not sure how else to handle them.
Should I use an interface and let either my Adapter or the fragment that creates that adapter implement that interface? Is this considered clean architecture? I couldn't find a clean architecture tutorial that uses adapters and complex layouts.
Thanks for any advice.
Related
I want to create List view row animation like below . I want to move row from one list view to other list view. Both list view are in same activity.
Anyone can give me idea how I can do this.
First of all because you mentioned "ListView":
In my opinion the best way to perform dynamic "lists" in android is to use to android-given class
RecyclerView.
It's easy to use like a normal ListView but like I said before it handles dynamic data.
Moreover it has some support librarys like ItemTouchHelper to drag/drop and swipe items in the list around. Its very easy to expand your RecyclerView with this upgrade. Here is a good tutorial:
Tutorial.
I would like to give you two ideas how I would proceed to implement such a list like the example of your post:
1) (Recommended) Search on Github or similar sites for 3rd library parties that already solved this.
2) Use the RecyclerView with the ItemtouchHelper-Upgrade i mentioned above and try to expand it with two lists. When an item is onMove() set the visibility of the first list on GONE and the second on VISIBLE. Now you only have to add the data of your item to the second list and remove it from the first. Then use notifyDataSetChanged() on both lists and your done.
I dont know how difficult it will be to implement it but thats the only way I know how you can do that and how the programmers of your example could have done it.
I was looking for a ListPreference in which the user can change the order of items from a list. The items would be draggable and can be re-ordered by the user.
I saw this in my custom ROM (and I'm almost sure I saw it in Cyanogenmod) for the QuickPanel. Here's a screenshot to get the idea through:
I know how I can make custom ListView items and set the icon to indicate that the items are draggable, but I don't know how to make them draggable, and change the order accordingly. As for saving them in the preferences, I found this which could be implemented easily.
PS: I know Cyanogenmod is open-source, but I couldn't find the source for this particular thing :( The closest I could get was this, which should be somewhere near the other screen...
Thanks in advance for any tip about this.
UPDATE: I ended up using the files from the accepted answer, with additions and modifications. I am listing them here for further reference.
Use a custom Adapter (ArrayAdapter in my case), to implement the visual feedback that this item is draggable, which is an ImageView near the TextView. This is optional.
Set a DragListener and RemoveListener to update the list accordingly. The ListView does not do that automatically. And it depends on the Adapter you are using.
There was a line that casted a View to a ViewGroup, it made some errors, so I removed the cast without any issue, it was not needed. (in the onInterceptTouchEvent method).
Change mRemoveMode = 1; in the constructor of TouchInterceptor, or one of: FLING = 0; SLIDE = 1; TRASH = 2;. I think for TRASH, a resource should be available too.
I actually took the file not from the answer's link but from the Cyanogenmod one, which I already had, but I guess these files were the same.
These are the actual files in the project (at r12, at the time of writing):
The Preference using this ListView
The ListActivity with the listeners and the Adapter
The actual ListView
I hope it helps somebody else :)
There is no built-in widget to do this, but you may want take a look at the custom implementation used by the AOSP music player to allow for re-ordering of songs in playlists.
TouchInterceptor.java
That's the class which is extending ListView and is responsible for handling all of the MotionEvents and re-ordering its items, as well as detecting swipes for deleting items. You can see it implemented into an activity here in the TrackBrowserActivity.java class.
It has three interfaces you should also be aware of: DragListener, DropListener, and RemoveListener. You can use these interfaces to provide it callbacks to fire for those events, so that you can update changes made to the list order to your SavedPreferences (since the ListView will not handle that for you).
You can easily extend or modify the TouchInterceptor class to add additional functionality since the low-level stuff is all there for you.
So I have an activity that will display a list of options and when you click an option it should move to a list that displays the choices for that option, but I'd like both lists to be in the same activity.
I'm debating between the two options of using a single listview and changing the contents (maybe by swapping the adapter if that works, not sure) whenever a user navigates between the two lists, or using something like a viewswitcher where both lists exist independently, but only one is visible at a time.
I would definitely think the viewswitcher option would be the cleaner option, but how will it perform especially if I need to scale it to more than two lists? Is there much overhead to creating a listview that's not rendered?
Keeping one listview and switching out its backend would be a pain, especially considering all the re-initialization every single time you click an option.
-Use two ListFragments, have one control the other. Using Fragments instead of two separate ListActivities would mean that when you build a tablet interface, it would be minimal work to have one Activity with both on the same screen.
-Use an ExpandableListView
I did have a choice like that. I was using a list view to navigate to a remote webdav server.
At the beginning I was using one view for each folder. It was cool: using back was allowing me not to worry about navigation history.
But after a while, there was some cases where I needed to manage all the views at once, or kill them all or implement a communication between views (for parameters). And it was a nightmare to achieve. Also my list were beginning to be heavy and a lot of list in memory is never a good thing. I finally gave up and managed all the navigation in a unique list view. I should have do it at first.
my app is a social network where users share links and tag them to let the right persons receive it. Basically, the main activity is simply a listview of posts. I use an open protocol parser to get the web objects metadata on server side.
Now I need to display the right layout in each post item depending of the metadata (video, app, web page, ...). And of course, layouts must react to user clicks event and call intents.
So my first idea is to have a framelayout for each item where I load a specific fragment in charge of generating the right layout depending of the resource type.
But I'm really not sure loading a fragment inside a listview item is a good practice as the reuse system of views is totally messed up.
I'd just like to know what is the best way to implement this functionality for you guys.
Thank you.
This is not really what fragments are designed for. You do not need to use fragments to have ListView rows of differing types -- just override getItemViewType() and getViewTypeCount() in your ListAdapter, then be sure to create the right type of row on demand based upon the metadata.
I need some valuable advice from you guys...
I have a UI where I have to drag objects from one view to another.
I have a rough sketch of this UI below
I think I have to create a custom view for this. I have to drag a square and a ball from bag 1 and bag2 [both bags are scrollable, can contain 10 to 60 items each] and drop it to the closet one by one. and later I have to find the number of items in the closet. The items in the closet must be arranged in a well maintained fashion [may be ...like 6 in a row].
Where should I start?
How many custom views should I use?
Is there a simple and effective UI solution for this?
Happy coding..!
I would suggest a design with three different GridView objects laid out inside a ViewGroup that supports dragging objects from one GridView to another. The objects would be custom ImageView subclasses so you'd have a place in code to support a drag-and-drop protocol of some sort and because you'd likely want to associate some data that is specific to your application with the objects being dragged.
As for the drag-and-drop protocol, you could consider an adaptation of the Android Launcher drag-and-drop framework or the current drag-drop classes described on the Android developers' website. I don't have much to say about the current drag-drop classes. I have not tried them yet, but understanding them is on my to-do list. However, I have done an adaptation of the Launcher code, and I have written it up on my blog and posted demo apps and source code there. See Drag-Drop for an Android GridView.
With the framework that originated in the Android Launcher, you have a good set of classes and interfaces to work with. Some of the objects include: DragLayer, DragSource, DropTarget, DragController, DragView. The DragLayer is a custom ViewGroup within which all drag-drop operations occur. It delegates handling of all the touch events to a DragController, which is the object that does the actual moving of objects around on the screen. As it does so, it interacts with DropTarget objects to give the user visual feedback that something is being dragged and that a place to drop something is available. A DropTarget is an object where something can be dropped. A DragSource is the interface for objects that can be dragged within the DragLayer. The Launcher framework is a good one because it gives you a way to think about dragging and dropping and how you want to divide up the responsibilities defined by the framework.
The reason I suggest GridViews for your problem is it sounds like you are thinking that way already. The closet has "maybe 6 in a row" so that could be a GridView with one or more rows depending on how screen space you have. A GridView would also work for the container that holds the squares and circles. If that is a good fit, you could study the code in my drag-drop tutorial and see if that makes it easy for you to move objects from one GridView to another.
In my demo program, I ended up with a custom subclass of ImageView that I called an ImageCell. These are views that are on the grid. An ImageCell allows objects to be dragged from them and onto them. For awhile as I worked on the tutorial, I had a custom GridView class too but ended up with the standard GridView. It sounds like you'd want a custom GridView because it sounds like being in the closet is different than being in the other sections. Having it gives you a convenient place for the methods you have not thought of yet.
I hope some of these suggestions prove useful.
Depends on the Android version you are targeting. For 11 and above you can use the built in drag and drop functionality, otherwise you are pretty much on your own. I would normally advice you to implement some sort of a long press action that might even allow you to select multiple items and move them in batches, which would be a really simple thing to implement.
If you really need DnD you should check out this example, it should give you some idea on how to make your own implementation.
I think that bag1, bag2 and closet can be three instance of the same configurable custom view (let's name it CustomBagView).
CustomBagViews should be responsible for displaying items (using a gridview of imageview for example).
I think those will not need to handle drag & drop directly but they should support
removing and adding elements
provide a setOnItemTouched(Interface_class) callback setter.
Then you will need to code a Container custom view (let's name it BagContainerView) that will contain the three bags and handle the dragging & dropping from the bags.
You will provide a handleDrag callback to each bag using CustomBagView.setOnItemTouched, then track the finger motion in it.
When the dragging finishes, you must find where it ends, locate the right 'customBagView' and ask it to add the item to its list.