How to dynamically update bitmap with rounded corners on Widget root layout? - android-layout

I need to dynamically update a picture with rounded corners in the root layout of the Widget. There is only a simple setImageViewBitmap API for viewing related documents, but the exact size of the widget is required to draw the specified radius; this problem is easy to implement on Android 12 (refer to https://medium.com/androiddevelopers/updating-your-widget-for-android-12-92e7de87424c), but I see that some apps are also implemented on devices lower than Android 12, there should be other ways to achieve this problem
As I know is:
Before Android 12, I can't get real size of widget root view
Many APIs of RemoteViews are only supported in API 31 and above,including setClipToOutline, etc.
The View supported by RemoteViews is very limited and does not support custom View
my widget layout file:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fl_root_view"
android:layout_width="match_parent"
android:layout_height="155dp">
// widget background
<ImageView
android:id="#+id/iv_root_view_bg"
android:src="#drawable/big_most_played_widget_layout_bg"
android:layout_width="match_parent"
android:layout_height="match_parent" />
// widget content
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal">
...
</LinearLayout>
</FrameLayout>
one of the background files:
//#drawable/big_most_played_widget_layout_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="24dp"/>
<solid android:color="#182327"/>
</shape>
And i have tried:
Update the layout background directly, the rounded shape will be lost
Generate a bitmap with the approximate width and height of the widget and use PorterDuff.Mode.SRC_IN to draw rounded corners, which has great uncertainty on various devices (the bitmap cannot completely fit the widget size)
override RemoteViews.apply(), but it not work
override fun apply(context: Context?, parent: ViewGroup?): View {
val result = super.apply(context, parent)
val colors = IntArray(2) { (0xff000000).toInt() or Random.nextInt(0x00ffffff) }
val bgDrawable = GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors).apply {
cornerRadius = 42f
}
result.setBackgroundDrawable(bgDrawable)
return result
}
I want to know:
In addition, is there a way to get the real width and height of the widget on devices lower than Android 12?
Other better implementation methods?

Related

How to slide Text from left to right using marquee

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.

How to allow a layout to occupy all the space not used by other layouts

I have a RelativeLayout
<RelativeLayout
<RelativeLayout ID = TOP
<!--Height = wrap_content -->
</RelativeLayot>
<RelativeLayout ID = MIDDLE
<RelativeLayot ID = mid1
<!-- Placement Below TOP, allign ParentStart -->
<!-- Height = wrap_content -->
</RelativeLayout>
<RelativeLayot ID = mid2
<!-- Placement Below TOP and right of mid1 -->
<!-- Height = wrap_content -->
</RelativeLayout>
</RelativeLayout>
<RelativeLayout ID = BOTTOM
<!--Height = wrap_content -->
<!-- Placement below MIDDLE, alligne Parent Bottom
</RelativeLayot>
</RelativeLayout>
My requirement is this, Hight ofTOP and BOTTOM Layouts shout be of their content and the MIDDLE layout remaing space in the middle and its contents should be centered horizontaly and vertically. I tried height =0- and layout weight but anot able to achieve this.
I used LinearLayout instead, for MIDDLE used layout_height='0dp" and layout_weight="1". It solved the problem

Making a stackable, square graph with text labels

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?

Align 3 stretched Textview in a row in Relative Layout prgramatically

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);

Android: Using LayoutParams to set width of View object

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.

Resources