I've got a task to display N*N matrix in Android app.
Numbers in this matrix should be in the specific order, like this:
matrix example image
The main trouble is that i should display each cell of matrix with animation with some delay (matrix shouldn't be visible at first and then cells appear, one by one).
How can i achieve this kind of effect? Should I use GridView with custom adapter, or I should create my own view by extending "View" class? Thanks in advance.
I'm not sure how large your matrix will get but I'd recommend you implement this using a RecyclerView with a GridLayoutManager, especially if your grid matrix may have variable number of elements.
In a simplified overview, you can achieve this by creating a RecyclerView in your layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
And then in your the Activity, apply the GridLayoutManager to this RecyclerView which will place each cell (which you will also need to define using a layout and inflating it in the RecyclerView's onBind method) in a grid layout as you'd like.
I suggest you see this Stack Overflow post that explains pretty much exactly how to achieve this.
For animations, you can get access to each cell's View via the RecyclerView.Adapter that you will define (see the aforementioned post). You probably will want to start each cell with visibility set to gone or invisible then reveal them however you'd like.
If you know your grid size is fixed and relatively small, you could still use a GridLayout which will spare you all the adapter code for RecyclerView.
Let me know if you're still having trouble understanding, hope this helps!
Related
I have a scrollable GridView where the items have a decent amount of empty space between them. for some of the objects in the grid, I'd like to add arrow images leading from one to the other
For reference to what I mean, think of the World of Warcraft talent trees (http://calculators.iradei.eu/talents/mage). You'll see some of the talents have arrows leading from one item to the next.
The layout I'm dealing with just contains a gridview in a framelayout, nothing else
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="4"
android:scrollbars="none"
android:id="#+id/talent_tree_grid_view">
</GridView>
</FrameLayout>
I'm trying to add these ImageViews in code, as I don't think there is any way I could add this logic into the adapter for the GridView.
I've tried adding them as children of the parent FrameLayout, based on the x and y coords of the GridView items, and this works, but when scrolling the GridView, the arrows do not also scroll
I've also tried adding them directly as children of the GridView, but it does not support this behavior (it throws java.lang.UnsupportedOperationException)
Are there any ideas as to how I could add these imageviews between the gridview items?
This sounds very similar to Romain Guy's "Shelves" app where a custom GridView is used and the background image of a bookshelf scrolls. Take a look at the project here. Source for the custom GridView can be found in the file ShelvesView.java in the source code. A quick intro from Guy Romain is here;
For the arrows, you may want to consider a 9-patch drawable.
I have investigated the above approach a little more and have a sample app based upon
Google's Hello GridView example.
Taking this example app, I have built a custom GridView (DogsGridView.java) and connected the photos across empty cells similar to your example of World of Warcraft talent trees. I just use simple lines, but the class can be modified to connect cells with arrows or another graphic.
Here is a quick video with connecting lines. Here is another with 9-patch arrows.
The project source can be found here.
Good day,
I am working on an application, and I want to design the view below, I am unsure which view to use.
From my experience with Android development, I'm thinking it should be a list view or a recyclerview with a custom header, I may be wrong, but looking at the view could someone explain what view I should use. I have red arrows indicating what I am talking about.
I was thinking a custom scrollable list view, and defining the list of items, shown by the three arrows, basically three custom list items.
Should it be a list view or recyclerview with a custom header for the arrow marked as 1.
Should the arrow marked as 3. be a gridview that's filled dynamically? As I understand it, the gridview doesn't work well with a scrollable parent, like a listview, as I want the whole view to scroll based on the content, like in Instagram, what is a good approach to accomplish this.
I came here because I have searched and really couldn't find any good advice
Thanks in advance
It seems that you don't need one single RecyclerView here. You can use a combination of ViewGroups and Views. Simple example:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Code for 1,2-->
<!-- Your grid from 3-->
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
</ScrollView>
Edit:
Also do this on your RecyclerView: setNestedScrollingEnabled(false).
This will make your whole layout scrollable, while your RecyclerView, having a height of wrap_content will just expand(adding to the height of the whole layout) without the need for internal scrolling.
the xml file:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="#+id/singleProp"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:visibility="gone">
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:id="#+id/propertyImg"/>
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/propertyData"
android:layout_below="#id/propertyImg">
</ListView>
</RelativeLayout>
With the above codes, the image will be fixed at top-center position. With CSS terms in html, the style of that image view is style="position:fixed" but what I want is style="position:relative".
For example,
I hope the picture can illustrate the idea.
May I know how I should modify my codes?
Let me elaborate a bit more on mark.zhai`s answer, since it's the only one that I find to be the proper approach.
First of all I wanna point out that you should think about implementing your list with a RecyclerView instead of ListView (right now it's generally favoured to use a RecyclerView; ListView is getting kinda deprecated)...
If you want to be sure that your ImageView works nicely (scroll-wise) with your list (without too much "side-work" on scroll integration), you should implement it as a first item of your list. If you stick with your ListView you can use the header function of it and add your ImageView with ListView's method addHeaderView. If you decide to move to a RecyclerView (which I think you should), you can accomplish that in a bit more difficult manner (more on that for example here).
why don't u make the imageview an item of the listview
For this you need to create a custom listview which having the first item as a image view and later having all your list items. Probably you can control this in your adapter getview method by the use of position(int)
For example if Position is equal to '0' show only image view and if position is not equal to '0' show your rest elements by using Visibility
Note: here their might be a chance of performance issues as it is loading the unnecessary views every time
To achieve this, you need to scrolling the complete layout. In general case, when you fling on a list view, only the item within the list view moves.
Check this link.
I'm not entirely sure what you're asking, as I don't know a lot about CSS, but you can check out this link which describes aligning elements within a Relative Layout.
You might want to try adding alignParentLeft or alignParentRight.
Remember margins are external to the object and padding is internal. For example to move the image 20dp from the left you would:
<ImageView
android:layout_alignParentLeft="true"
android:layout_marginLeft="20dp"
android:layout_width="200dp"
android:layout_height="200dp"
android:id="#+id/propertyImg"/>
Here are some useful links about mastering Relative Layouts:
Relative Layout Params
Moving Elements Around in a Relative Layout Tutorial
Another RelativeLayout Example
Margins and Padding
Why don't you use layout_below to take your layout below whatever you want, and use layout_gravity to set it's gravity. You can check these Link to get you better understand, it will help you in these problem.
I am trying to achieve the layout represented by the following image, using an adapter to compose the internal views:
All rows scroll together and recycling is in place.
I have not seen many approaches on SO or any of the blogs. FlowLayout doesn't allow scrolling, StaggeredGridView (Etsy's or Google's) doesn't allow for rotation, and synchronized multi ListView seems too involved.
What is SO approach to this custom component?
My approach would be to tie together n horizontal listviews in a single viewgroup. Listen to touch events on the viewgroup, and scroll all the 3 horizontal listviews together.
Layout would be like this -
LinearLayout(vertical)
--HorizontalListView1
--HorizontalListView2
--HorizontalListView3
--HorizontalListView-n
Now forward all the touch events to the parent viewgroup, and handle them in a single toucheventlistener. In the touchevent listener, calculate a scroll for all horizontal listviews, and call the corresponding scroll.
As all the scroll calls are done in a single call on UI thread, they should be processed in the next drawing pass. This should make it feel synchronized. If this doesn't work, you need to explicitly synchronize the views by extending them.
With this you will have view reuse and recycling as far as possible with horizontal listview. All views should scroll together if synchronization is in place.
Just an idea - use simple HorizontalScrollView with a single LinearLayout inside (the HSV has a requirement for only one child). Inside that LinearLayout place vertically another 3 LinearLayouts - one for each row. Inside each of the 3 layouts place (horizontally) the items that belong to one row. I haven't tried this but it would be the first thing I'd try if I was in your situation.
Something like:
<HorizontalScrollView>
<LinearLayout android:orientation="vertical">
<LinearLayout android:orientation="horizontal" />
<LinearLayout android:orientation="horizontal" />
<LinearLayout android:orientation="horizontal" />
</LinearLayout>
</HorizontalScrollView>
I think the best way for you is to extend ViewGroup and implement this component by yourself. Also extend BaseAdapter and create methods like gerFirstRowView, getSecondRowView and so on. You will be able to implement effective view recycling and avoid heavy nesting of views so your component will have good performance.
Use GridLayout with orientation as vertical, with your height the constant value for the 3 rows of ImageViews. Scale each ImageView to match the constant height in your adpater. Set the image to your android:src in XML or setImageResource in Java. This will scale the images accordingly without stretching.
Then add all your horizontal scrolling code.
I have an activity with a GridView inside it. The ActionBar is set to overlay mode.
Right now, you can only see half of the first image because the ActionBar cuts it in half.
How do I add padding to the interior of the GridView so that it initializes in such a way that you can see the entire first image? Or is there another way? For example, how would I go about extending GridView to create one that has a built-in configurable, dynamic gap at the front?
example (although ListView instead of GridView): reddit is fun app: https://play.google.com/store/apps/details?id=com.andrewshu.android.reddit
edit: I'm hiding the ActionBar whenever the user scrolls down at a certain rate or past a certain level.
Use a ViewTreeObserver.OnGlobalLayoutListener in your Activity or Fragment to determine the number of columns your GridView will display (presuming it varies based on screen size and orientation), then use that number in your Adapter implementation. In getView(), if position is less than the number of columns, return an empty view whose height matches the Action Bar, otherwise bind your data as you would normally.
There is an excellent example that does exactly what you want in Google's "Displaying Bitmaps Efficiently" sample application: https://developer.android.com/training/displaying-bitmaps/display-bitmap.html
Here is the relevant source code:
https://android.googlesource.com/platform/development/+/master/samples/training/bitmapfun/src/com/example/android/bitmapfun/ui/ImageGridFragment.java
Try adding android:layout_marginTop="?android:attr/actionBarSize" to the parent of your GridView, or the GridView itself if it doesn't have one.
This will push your layout down so that it rests below the ActionBar.
Edit
You may want to conside using a ListView instead of a GridView. Reason being, you can easily achieve that effect by creating a fake header and then calling ListView.addHeaderView. You can't do the same with a GridView. What you're talking about can definitely be done with a GridView, but it will require you to subclass it and modify it quite a bit.
Header
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?android:attr/actionBarSize" />
Having ActionBar in overlay mode, the following works for me:
<GridView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?android:attr/actionBarSize"
android:clipToPadding="false"
android:numColumns="auto_fit"
android:columnWidth="120dp"
android:verticalSpacing="8dp"
android:horizontalSpacing="8dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:id="#+id/gridLibrary" />
The most important lines here are: android:paddingTop and android:clipToPadding.
In my application, when I open an activity with the gridview above, the first row is fully visible. Then, when I scroll down, the ActionBar hides and the gridview fills up all the screen.