Android custom container (hexagonal) withe adapter - java

I want to create a custom android container. Where I can easily add and remove objects. The container should place objects inside hexagons. The order in which objects places is really important and shown in the image below. Objects in this adapter are click-able ImageViews (circular).
It is even possible to make something like this for Android?
I know that there were similar questions like mine, but there are not even close to what I want to achieve.
Probably more and more people where looking for more custom containers like that one I'm trying to make. Not the standard one like in other apps: GridsView, ListView, etc.
What I've already made
I decided to use RecyclerView and custom RecyclerView.LayoutManagers. Also write an algorithm to define a position of ImageViews. Unfortunately I'am not familiar with LayoutManager and not sure how should I define places using it Interface.
RecyclerView
Here is algorithm:
List<Object> list;
int nuberOfElements = list.size();
int layerNr = 0;
int radius = 0;
int angle = 0;
//handle first middel element postion(0,0)
nuberOfPlaceElements --;
radius += r;
for(layerNr=1; nuberOfElements > 0; layerNr ++){
for(int elementInLayer = 0; elementInLayer < layerNr * 6; elemnetInLayer ++){
//layerNr *6 -> define how many elements in layer
angle += 360/layerNr * 6
//handle the postion of elemnts in Layer
nuberOfElements--;
}
radius += r;
angle = 0;
}

best solution is to create a custom layout (http://lucasr.org/2014/05/12/custom-layouts-on-android/) but that's also the most expensive way (cost on time to implement)...
alternative you can create a custom view and draw images directly there (http://developer.android.com/training/custom-views/custom-drawing.html)
all you ever want to know about hex-maps: http://www.redblobgames.com/grids/hexagons/
why is layout better than a custom drawing view? it can be packed in a library and used for any other application whereas a custom drawing view is rather bound to the application...

you can check this library which does exactly what you are asking for
https://github.com/xresco/Hexagon-Recyclerview
It's super simple to use.
Instead of using the default recyclerview (or listview) just use
<com.abed.hexagonrecyclerview.view.HexagonRecyclerView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/rvItems"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
app:items_count_in_row="3"
app:items_horizontal_spacing="20dp"
app:items_vertical_spacing="20dp"
app:orientation="horizontal" />
you can customize it using the following four parameters:
app:items_count_in_row
app:items_horizontal_spacing
app:items_vertical_spacing
app:orientation

Related

Can Lazy Column live inside another Lazy Column?

I'm starting using Jetpack compose and i'm facing some issues with Lazy Column.
The problem is that i want to make a list that contains another list inside every root item (such as a card that containt another list inside).
Unfortunately, when i run the following code (below the snippet that resume what i'm trying to do).
I catch the exception:
java.lang.IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed. One of the common reasons is nesting layouts like LazyColumn and Column(Modifier.verticalScroll()). If you want to add a header before the list of items please add a header as a separate item() before the main items() inside the LazyColumn scope. There are could be other reasons for this to happen: your ComposeView was added into a LinearLayout with some weight, you applied Modifier.wrapContentSize(unbounded = true) or wrote a custom layout. Please try to remove the source of infinite constraints in the hierarchy above the scrolling container.
Code:
LazyColumn(modifier = Modifier.wrapContentHeight()) {
items(list.value) {
item -> LazyColumn(modifier = Modifier.wrapContentHeight()) {
//some Text
}
}
}
I don't need the nested Lazy Column to be scrollable, so i'm wondering if for this purpose there is another element to use instead of LazyColumn, or i'm making some other mistake.
I've also tried to put in item{} block other layout elements, as suggested by the Exception, but with the same result.
No, unfortunately, nesting scrollable composables in the same direction is not allowed.
It's not supported in jetpack compose, but I think it should be supported because many use cases need that. e.g e-commerce applications,food delivery (like DoorDash)

How to add ID to programmed layout item (android) in JAVA

I am adding multiple elements to layout in Java code. For example java coded before imageview to known layout with some layoutparams.
layout.addView(imageview, layoutparams);
I asume that I can't do it in XML because I don't know how many elements will be added (determined by user).
I need to set and know IDs to those added elements so I can refer to them later on.
What I need is something like (before adding):
imageview.setId(??);
Is this a good method to use? If so how do I use it?
My main consern is that I am not sure how R.id works exactly.
Can I for example make those IDs like 100001, 100002, 100003... ? Won't I override any?
I will store those IDs in an list/array for use later in code.
public static int generateViewId ()
Added in API level 17 Generate a value suitable for use in setId(int).
This value will not collide with ID values generated at build time by
aapt for R.id.
What if it will colide during runtime because of multiple methods adding elements. Are there any sql-like transactions?
BTW: Going for API17 isn't exactly what I want. Slightly over 50% of the market.
If you need to get a reference to a certain View that is added dynamically to a bunch of other similar Views, you might want to use a loop similar to the one below:
for(int i = 0; i < parent.getChildCount(): i++) {
View view = parent.getChildAt(i);
}
If you need more control than that then you may want to check out the View.setTag() method. Using this, you can create a unique tag for each View and retrieve it later on in a loop.
final ImageView imageView = (ImageView) findViewById(R.id.imageview);
imageView.setTag("I'm a tag!");
for(int i = 0; i < parent.getChildCount(): i++) {
View view = parent.getChildAt(i);
if(view != null && view.getTag() == "I'm a tag!") {
// Do something with the View
}
}
Although the code above should work, I might suggest approaching the issue from a different angle depending on what you intend to do with the Views.
It is needed the ID to be unique for the findViewById method to work properly. However there is no guarantee that the ID is unique in the context of a ViewGroup. If you use the xml way to generate a layout, the android build tools generate unique IDs for all elements but if you create and add them manually to the container, the ID is not generated. If there are multiple views with equal IDs, the findViewById method will return the first view from the tree view structure with ID equal to the given one.
You can use safely the generateViewId() method. There is no need to synchronize its usage (transactions as you call them) because the android guys have already done this for you. You can use it safely without worrying for duplicate ids.
I hope this will help you understand the concept and the need of the IDs :)
AFAIK, imageview.setId(); won't harm your resource identification through getting this source from R file, but in your case, I'd prefer use tags:
imageview.setTag(100001);
and to get it:
int id = Integer.parseInt(imageview.getTag().toString().trim());
And if you are already using the view tag somehow, you can give it another tag with a key like your app-name:
imageview.setTag(R.string.app_name, 100001);
and to get the id:
int id = Integer.parseInt(imageview.getTag(R.string.app_name).toString().trim());

can we auto swap the images in lwuit

I mean as a slider, like so:
Image img[]=new Image{"a.png","b.png","c.png"};
for(int i=0;i<img.length;i++){
limg = (new CustomLabel(img[i]));
cnti.addComponent(limg);
addComponent(cnti);
}
Sorry, I hope you all getting my question.
You can place a Label then replace it using Container.replace() while using a slide transition.
If you want to allow the user to swipe then you can theoretically you can use a a horizontal list but there were some bugs there in LWUIT.
There are more powerful options in Codename One including ImageView.

Changing GridLayout row/column count at runtime in android

I am new in android development. I am trying to use a GridLayout to fulfill my UI design.
This is the scenario:
I defined a GridLayout in xml file as following
<GridLayout
android:id="#+id/gridLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#id/linearLayoutBottomLeft"
android:layout_alignParentLeft="true"
android:layout_below="#id/linearLayoutTopLeft"
android:layout_toLeftOf="#id/textView" >
</GridLayout>
Then, I set it in my activity's onCreate() method like following:
GridLayout gridLayout = (GridLayout) findViewById(R.id.gridLayout);
gridLayout.invalidate();
int rowNumber = 4;
int colNumber = 4;
gridLayout.setRowCount(rowNumber);
gridLayout.setColumnCount(colNumber);
so far so good, everything is working well.
However, I also have some buttons there. In button's click event, I changed the rowNumber and colNumber, set them at runtime. It cause some error I think...
So my question is whether the row number and column number can be set at runtime for gridLayout.
If this is not allowed in android, what is a good practice to realize a GUI like what I described above.
Any help would be appreciated.
You'll need to do a gridLayout.removeAllChildren().
Invalidate is a way of letting the View system know that the content of the View has changed and that it needs to be redrawn.
Today, I figured out some way to solve this problem.
In the xml file, I replaced the GridLayout with a LinearLayout, and made the girdlayout dynamically added as the child of linearlayout. Now the row/column count can be changed in button click event handler.
I am not sure if this is a good way to do it and any performance hit will arise.

How to set textview position constant in runtime?

I am trying to display some textviews visible in runtime.
Here's my code:
for (int i=0; i<arrBool.length; i++) {
arrBool[i] = r.nextBoolean();
if(arrBool[i]==true) {
textView[i].setVisibility(View.VISIBLE);
}
}
When I run the application, textviews should randomly be visible. It is working, but my problem is I have set the layout of those textviews. When I run Android Application, the visible textviews go to top left corner and loses the layout position.
How to deal with this?
Change start visibility parameter of views to View.INVISIBLE
It will hold their own places on the layout and prevent from taking this places by other views, which is normal behavior in case of View.GONE
Adding more to teoREtik solution.
In your layout do not specify the android:visible property.
for (int i=0; i<arrBool.length; i++) {
arrBool[i] = r.nextBoolean();
if(arrBool[i]==true) {
textView[i].setVisibility(View.VISIBLE);
else
textView[i].setVisibility(View.INVISIBLE);
}
}
I don't think using the FOR loop will help you out making the random possibility of the visible text view everytime you open. Why don't you just use the integer (0 for false and 1 for true) and a Random like this:
Random rnd = new Random(1); // --> This will randomize numbers up to one;
int enable = rnd.nextInt(); // --> Get the random value from 0 to 1
if(enable == 1) // --> If visibility of the text field is enabled everytime you opened the app...
{
textView.setVisibility(View.VISIBLE);
} else {
textView[i].setVisibility(View.INVISIBLE);
}
You can modify more and experiment on the randomizer for the integer's value by visiting this example at " How can I generate random number in specific range in Android? " topic. Check all the possible answers. Don't mind the green check mark and focus these answered codes by investigate its comments. I'm sure all of these answers about "random" topic, the link I gave you, is guaranteed effective.
About the layout, I recommend not to use the relative layout and instead use the linear layout because using the linear layout stays on the original place proportionally since relative layout is screen resolution dependent on the coordinates. Also try practicing manipulate the string value dimensions under res folder to maintain the size of the text proportionally in different screen resolution (from HVGA to WVGA). Check at " Different font sizes for different screen sizes " for more details about text size proportion.

Categories