For my first venture into Android-land, I have what seems to me to be a simple project. I want to display a square graph with text in its four corners. I want to be able to display a single graph, or four, grouped 2 x 2.
Quad graph example
So far, the only means I've found to overlay the four TextViews on my custom GraphView is to put the GraphView in a RelativeLayout, and position the TextViews relative to it.
<?xml version="1.0" encoding="utf-8"?>
<com.companyname.graph.GraphLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<com.companyname.graph.GraphView
android:id="#+id/graph_single_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/colorGraphBackground"
/>
<TextView
android:id="#+id/label_top_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/graph_single_view"
android:layout_alignStart="#+id/graph_single_view"
android:layout_alignTop="#+id/graph_single_view"
android:layout_gravity="top|start"
android:gravity="top|start"
android:hint="#string/placeholder_top_left"
/>
<TextView
android:id="#+id/label_top_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="#+id/graph_single_view"
android:layout_alignRight="#+id/graph_single_view"
android:layout_alignTop="#+id/graph_single_view"
android:layout_gravity="top|end"
android:gravity="top|end"
android:hint="#string/placeholder_top_right"
/>
<TextView
android:id="#+id/label_bottom_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/graph_single_view"
android:layout_alignLeft="#+id/graph_single_view"
android:layout_alignStart="#+id/graph_single_view"
android:layout_gravity="bottom|start"
android:gravity="bottom|start"
android:hint="#string/placeholder_bottom_left"
/>
<TextView
android:id="#+id/label_bottom_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/graph_single_view"
android:layout_alignEnd="#+id/graph_single_view"
android:layout_alignRight="#+id/graph_single_view"
android:layout_gravity="bottom|end"
android:gravity="bottom|end"
android:hint="#string/placeholder_bottom_right"
/>
</com.companyname.graph.GraphLayout>
To keep the GraphView square, I'm doing this in the GraphView class:
#Override
protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec )
{
super.onMeasure( widthMeasureSpec, heightMeasureSpec );
int size = Math.min( getMeasuredWidth(), getMeasuredHeight() );
setMeasuredDimension( size, size );
}
(stolen from here).
I'm running into problems, though, in displaying the group of four. GridLayout loses its tiny mind at the thought (it puts every GraphView in an area the width of the entire screen). I ended up using two horizontal LinearLayouts in a vertical LinearLayout, sized using layout_weight, which works, but won't let me do the animated transition that I want. I'd like a single graph simply to expand to cover the entire area, clipping its unchanging siblings as it goes, and back again.
So far I've settled on animating the layout_weights in the LinearLayouts, but the effect isn't something you'd show off to your friends.
I'm using height and width of WRAP_CONTENT for everything except 1dip-wide/tall separator lines between the graphs in the two rows, and between the rows in the quad view.
So my (first) question is - is there a better way to make my graph-plus-text widget?
Related
My Codename One app has to feature something like Android Chip controls, or equivalent.
They are used in two places and the layout is:
-for the first place
<com.google.android.material.chip.ChipGroup android:id="#+id/chip_group" android:layout_width="wrap_content" android:layout_height="wrap_content">
<com.google.android.material.chip.Chip android:text="#string/first_chip_title" android:id="#+id/first_chip" android:layout_width="match_parent" android:layout_height="wrap_content" app:closeIconEnabled="false"/>
<com.google.android.material.chip.Chip android:text="#string/second_chip_title" android:id="#+id/second_chip" android:layout_width="match_parent" android:layout_height="wrap_content" app:closeIconEnabled="false"/>
...
...
</com.google.android.material.chip.ChipGroup>
-for the second place
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="#+id/chip_list"
...
...
android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="0dp" android:layout_marginRight="0dp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" tools:listitem="#layout/content"/>
</LinearLayout>
where the content (it's the element of the RecyclerView) is:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">
<com.google.android.material.chip.Chip android:id="#+id/chip_element" android:layout_width="wrap_content" android:layout_height="wrap_content" app:closeIconEnabled="false" android:textAllCaps="false" android:layout_gravity="center_vertical" style="#style/Widget.MaterialComponents.Chip.Filter" android:layout_weight="1" />
</LinearLayout>
(Some layout parameters are included as they are in the code although they are not important here)
here's the effective layout (the example is for the second type of layout, the first one is just a simpler version):
What could be the equivalent in Codename One?
Flow layout breaks lines pretty seamlessly. It's the default layout for Container. I can use labels or buttons to build stuff like that pretty easily. Notice I didn't use UIIDs here which you need to use to add margin/padding so the chips are more distinct from one another:
Container chips = new Container();
// note you can use Button to make them clickable and UIID to style
// them any way you want
chips.add(new Label("a very long label for a chip"));
// I can check the chip manually
Label checked = new Label("another label");
checked.setMaterialIcon(FontImage.MATERIAL_CHECK);
checked.setTextPosition(RIGHT);
checked.getAllStyles().setBorder(RoundBorder.create()
.rectangle(true)
.color(0xaaaaaa));
chips.add(checked);
chips.add(new Label("chip label 2"));
chips.add(new Label("chip label 3"));
chips.add(new Label("chip label 4"));
chips.add(new Label("chip label 5"));
chips.add(new Label("short label"));
chips.add(new Label("very long label for chip"));
hi.add(chips);
I am using marquee.In my Android app Say original value pf text view is aaabbbccc and its fitting inside the view. So my marquee's output will be : aaabbbccc auto sliding from right to left. But instead of this i want to slide this aaabbbccc auto sliding from left to right. How can i do this....Below is my xml file.Thanks`
android:id="#+id/txt_MainScreen_Winnerlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_marginLeft="-10dp"
android:layout_marginTop="0dp"
android:layout_marginRight="20dp"
android:ellipsize="marquee"
android:focusable="false"
android:focusableInTouchMode="false"
android:fontFamily="#font/proximanovaregular"
android:gravity="center"
android:marqueeRepeatLimit="marquee_forever"
android:paddingTop="2dp"
android:paddingRight="25dp"
android:scrollHorizontally="true"
android:singleLine="true"
android:text="Exchange1:(00.14-2.30) Exchange2:(01.00-2.30) Exchange3:(05.00-6.30) Exchange4:(12.14-2.30) Exchange5:(10.00-12.30) Exchange6:(00.30-2.30) Exchange7:(03.00-05.00) "
android:textSize="13dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />`
Default system scrolls from right to left. Use animation for left to right scroll.
Animation animationl2r = new TranslateAnimation(-400,400, 0, 0);
animationl2r.setDuration(12000);
animationl2r.setRepeatMode(Animation.RESTART);
animationl2r.setRepeatCount(Animation.INFINITE);
TextView textview = findViewById(R.id.textview);
textview.setAnimation(animationl2r);
Resize the screen area by changing 400 to any other value and duration to your desired time.
Please don't mark this question as duplicate. Why? because I am going to explain why it's not.
Below are the steps I have done:
Create a RelativeLayout
Created LayoutPArams for it as wrap_content and wrap_content
Created 1st TextView , gave it an id
Created LayoutParams for first textview and added it to the RelativeLAyout
Created Second TextView
Created LayoutParams for it, added a rule to be right_Of of id_for_first_tetview
Same step for Third Textview, except it's right_of the second textview
The problem here is: The first text view has text which extends to the second line, and when the text extends to the second line, the width of this i.e. the first textview occupied the whole width, and hence the other textview either overlaps or comes below it.
Let me demonstrate that with a diagram:
Want:
Happening:
So in short, is there a way to keep the textviews in one row and even if one textview takes up two rows, the second textview can start right after where the text for forst Textview ended ?
Thank you in advance. I could really use some help.
This can be done with LinearLayout with weight easily.
Method 1 - XML (give required padding or margins)
<LinearLayout
android:layout_width="match_parent"
android:weightSum="3"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/textView2"
android:layout_width="0px"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="TextViewTextViewTextViewTextView" />
<TextView
android:id="#+id/textView4"
android:layout_width="0px"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="TextView" />
<TextView
android:id="#+id/textView3"
android:layout_width="0px"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
Method 2 - Programmatically (give required padding or margins)
tv2 = (TextView)findViewById(R.id.textView2);
tv3 = (TextView)findViewById(R.id.textView3);
tv4 = (TextView)findViewById(R.id.textView4);
android.widget.LinearLayout.LayoutParams params = new android.widget.LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1f);
tv2.setLayoutParams(params);
tv3.setLayoutParams(params);
tv4.setLayoutParams(params);
In Android, I'm trying to accomplish this:
Basically, the ability to add the button side by side with an EditText, where they both take up 90% of the width of a top row. (I'm not concerned with having a logo like the twitter icon).
I've tried LinearLayout with layout_weight, but they didn't appear properly at all:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum = "1.0"
android:orientation="vertical"
android:background = "#faadadad" >
<EditText
android:layout_width="0dip"
android:layout_height="0dip"
android:layout_weight = "0.8"
android:layout_marginLeft = "2dip"
android:layout_marginTop = "1dip"
android:layout_marginBottom = "1dip"
android:hint="Search Terms" />
<Button android:text = "?"
android:layout_width = "0dip"
android:layout_height="2dip" android:layout_weight = "0.2"/>
</LinearLayout>
and anything I tried in RelativeLayout just didn't look right (I tried setting the margin between the 2 element to 0dips, no luck. Also I couldn't get the 90% of the width requirement either.)
What am I doing wrong? Thanks in advance.
Try using following:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum = "1.0"
android:orientation="horizontal"
android:background = "#faadadad" >
<LinearLayout android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8">
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft = "2dip"
android:layout_marginTop = "1dip"
android:layout_marginBottom = "1dip"
android:hint="Search Terms" />
</LinearLayout>
<Button android:text = "?"
android:layout_width = "0dip"
android:layout_height="wrap_content"
android:layout_weight = "0.2"/>
</LinearLayout>
So basically, when you using, horizontal LinearLayout, then layout_weight works horizontally i.e. width is divided according to layout_weight parameter (layout_width="0dp"). If you are using vertical LinearLayout, then layout_weight works vertically i.e. height is divided vertically according to layout_weight parameter (layout_height="0dp").
Hope it will be helpful to you.
I have a UI element that I am working with in my Android app that has a custom width. The UI element essentially is a block with two green circles - one circle on the left of the block, and the other circle on the right of the block.
I want to be able to set the width of the whole UI element programmatically. The circles should always have a constant size, and then the block sitting in the middle should size itself to fill up the rest of the space.
Here is what I currently have:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<View
android:background="#drawable/green_circle"
android:id="#+id/left_green_circle"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
/>
<View
android:background="#drawable/blue_rectangle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
/>
<View
android:background="#drawable/green_circle"
android:id="#+id/right_green_circle"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
I then set the layout parameters of the View in code like this:
int layoutLeft = block_x_position - green_circle_width;
int layoutWidth = block_width + (green_circle_width * 2);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(layoutWidth, block_height);
layoutParams.setMargins(layoutLeft, block_y_position, 0, 0);
this.setLayoutParams(layoutParams);
this.requestLayout();
I am using a RelativeLayout in the code above because the parent of this whole View element is a RelativeLayout. Unfortunately, I am not getting the results that I would expect. My "block_width" variable is "40dp", and my "green_circle_width" variable is "20dp". Here is what I am getting:
I have tried using "wrap_content" instead of "match_parent" in my View XML, but that doesn't have any affect at all. Any idea why my block is getting extended past the width that I would like it to be extended?
Thanks for any help.
You are seeing cut off circles because (I'd imagine) the width of the green circle images (jpg or png) is greater than 20dp. If you want to scale the green circles use an imageView and set the scaleType attribute.
Otherwise you're getting exactly what you want. By forcing the circle views to be 20dp, you're creating a lot of extra space for the block to fill up. Set the circle width correctly or use a scaleType and it will work.
As an aside, you probably shouldn't use match_parent as the width of the block (which implies it will take up the whole width, including the space that is supposed to be occupied by the circles). Instead use some arbitrary width (0dp for example) and set the layout_weight to 1.