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.
Related
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!
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 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.
I'm trying to port an app from iOS to Android. In my iOS app I have an image view which displays a map, and on top of it I want to display multiple button views on certain specific positions.
None of the standard views in Android seem to fit my needs, but I am surely missing something. How could I achieve this?
Thanks
The easiest thing to do would be to use any layout that's best suited for your needs (LinearLayout, FrameLayout, RelativeLayout, etc.) and set its background to any image you need. I believe the image will automatically scale to fill the corresponding Layout. Put the image into the appropriate drawable folders - and format your XML similar to this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/buttons"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background_image">
...
</RelativeLayout>
I have a LinearLayout with fixed view. I dynamically inject images in it (ImageViews) but I dunno in advance how many of them will be inserted. I'd like to have a layout where images wrap and go to a new line authomatically when they exceed the available width of the father (LinearLayout)
how do you recommend I should move?
thanks a lot
Define a Listview within the Linear Layout like below. Wrap your Linear Layout tags around it.
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:drawSelectorOnTop="false"
android:scrollbarAlwaysDrawVerticalTrack="true"
/>
Update this list view dynamically as you add images. This will solve your issues.
As I answered on a question asked a couple of hours before yours:
There is no layout manager in Android today that behaves like Swing's FlowLayout, where it wraps widgets onto multiple lines. It is theoretically possible for you to write one yourself, by looking at the open source code for LinearLayout, etc. and following the patterns they establish.
Sorry!