I'm trying to make a rounded shaped surfaceview. I've searched a lot but i couldn't find a good solution. what i'm doing right now is that, I've put the SurfaceView into a FrameLayout, then another View on top of it, either with a PNG mask, or a shape xml drawable. here it is
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="140dp"
android:layout_height="140dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#000"
android:orientation="vertical"
android:visibility="visible" >
<FrameLayout
android:id="#+id/videorecordview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_weight=".2" >
<SurfaceView
android:id="#+id/surfaceView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>
</LinearLayout>
<LinearLayout
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#drawable/rounded"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
But this is not a good solution and it is also not working perfectly. I want to customize surfaceview to a rounded shape. any help would be much appreciated. Thank you :)
A little hack. Put your surface view inside card view.
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/margin_normal"
app:cardCornerRadius="10dp"
app:cardPreventCornerOverlap="false">
<SurfaceView
android:id="#+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/margin_normal" />
</android.support.v7.widget.CardView>
Don't forget to add this to your gradle file to use CardView
compile 'com.android.support:cardview-v7:25.0.1'
Also this two line inside card view
app:cardCornerRadius="10dp"
app:cardPreventCornerOverlap="false"
Cheers happy coding
You can't change the shape of the SurfaceView's Surface.
A SurfaceView has two parts, the Surface and the View. The View part works like any other View. By default, it just acts as a transparent "hole", creating a window in the layout. All Views are rendered by the app onto a single layer.
The Surface part is a separate layer that sits behind the View layer (unless you explicitly change the Surface's Z order), so you only see it where it "shows through" transparent areas of the View layer. You can draw on the View layer to mask portions of the Surface, but you can't change the shape of the Surface layer itself. Layers are rectangular.
In many situations a TextureView can be used in place of a SurfaceView. TextureView offers greater flexibility because it's rendered by the app onto the View layer, but can be less efficient than SurfaceView.
More information can be found in the Android graphics architecture doc.
To achieve what you ask, it is very easy to do it.
You only need to use the next XML:
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="12dp">
<SurfaceView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</androidx.cardview.widget.CardView>
And to use this CardView, add this dependency on your build.gradle app:
implementation 'androidx.cardview:cardview:1.0.0'
try this
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
<gradient
android:startColor="#FFFF0000"
android:endColor="#80FF00FF"
android:angle="270"/>
</shape>
<SurfaceView
android:background="#drawable/circle"
android:id="#+id/surfaceView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
Related
I'm working on Android app with custom camera module. Main purpose of custom camera module is in adding overlay to camera - it should be something like outer transparent border (see first attached pic). It's actually blurred in the attached picture, but I need at least transparent effect as blur is not trivial to implement on Android.
The main point here is to ensure that "clear" visible area is corresponding to A4 format, so height divided by width should be √2 (main purpose of the app is in taking photos of A4 sheets).
I've figured how to achieve "inverted" effect - see second picture. But I can't get my head around on how could setup the view for the desired effect - first picture. Could someone share their thoughts on the problem? Here is the code:
camera.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="4">
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:id="#+id/overlay"
android:layout_width="316dp"
android:layout_height="446dp"
android:layout_centerInParent="true"
android:background="#drawable/overlay"
android:duplicateParentState="false" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="15dp"
android:background="#android:color/black">
<Button
android:id="#+id/button_capture"
android:layout_width="70dp"
android:layout_height="70dp"
android:background="#drawable/capture_button"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
<Button
android:id="#+id/button_close"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_centerVertical="true"
android:layout_marginEnd="50dp"
android:layout_marginRight="50dp"
android:layout_toLeftOf="#+id/button_capture"
android:background="#drawable/close" />
</RelativeLayout>
</LinearLayout>
overlay.xml:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/listview_background_shape">
<solid android:color="#88ffffff" />
I've found an article about just like what I needed. With little effort I could adjust the code there to get desired effect: https://blog.budiharso.info/2016/01/09/Create-hole-in-android-view/
To avoid tricky vector masks, it's enough to define the id/overlay as layout with 4 semitransparent rectangles, sharing the same drawable you use now: top, bottom, left, and right. You can determine the dimensions of each rectangle at runtime, but if you like intellectual challenges, you can define them as a ConstraintLayout.
I've just started with android and, in order to learn something, i'm simply trying to recreate some basic concept that i found on the web. My biggest question so far is which is the best method to draw a custom curvy shape in android. I know that similar question have been asked multiple times here, but i'm unable to find the solution to my problem.
I do not understand how to replicate a card like this. My only idea so far is to create curvy line in illustrator, save into svg and import in android as vector assets. At this point i was simply thinking to create a white rectangle and overlay the vectori assets. I absolutely don't think this is teh best way to do it but so far i don't know another way.
Thanks and sorry my english
either user CardView or create your custom view.
CardView
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="#dimen/scale_7dp"
app:cardElevation="#dimen/scale_5dp"
app:cardUseCompatPadding="true">
</android.support.v7.widget.CardView>
Custom View
create a shape in your drawable.xml folder
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/dull_white" />
<corners
android:bottomLeftRadius="#dimen/scale_5dp"
android:bottomRightRadius="#dimen/scale_5dp"
android:topLeftRadius="#dimen/scale_5dp"
android:topRightRadius="#dimen/scale_5dp" />
</shape>
Hope this helps you.
The best implementation would be to use CardView in your layout.
include
compile 'com.android.support:cardview-v7:21.0.0-rc1'
or any other version which is compatible with your existing support library.
after that, use this in your layout xml file
<android.support.v7.widget.CardView
android:id="#+id/card_view"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="#color/grey_300"
card_view:cardCornerRadius="10dp"
card_view:cardElevation="5dp"
card_view:cardUseCompatPadding="true">
place all the other views inside this cardview and you will get a curvy edge.
Add this dependency in app, this lib will give a rounded corner Image and other for cardview.
implementation 'com.makeramen:roundedimageview:2.3.0'
implementation 'com.android.support:cardview-v7:28.0.0-rc01'
In xml parent CardView and its Child RoundedImageView have same corner radius. I hope you know, how cardview works. Where "YOUR_DRAWABLE_HERE" is written please change it with your drawable
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
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:layout_margin="10dp"
app:cardElevation="0dp"
app:cardBackgroundColor="#00ffffff"
android:layout_width="match_parent"
android:layout_height="100dp">
<com.makeramen.roundedimageview.RoundedImageView
android:id="#+id/iv_look"
android:layout_gravity="center"
android:scaleType="fitXY"
android:src="YOUR_DRAWABLE_HERE"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:riv_corner_radius="10dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:gravity="center_vertical"
android:layout_height="match_parent">
<ImageView
android:layout_margin="20dp"
android:layout_width="100dp"
android:src="#android:drawable/btn_default"
android:layout_height="50dp" />
<TextView
android:text="YOUR TEXT"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.CardView>
In a custom view, OnMeasure and OnSizeChanged is used to set the instrisic size and get the final size respectively.
In OnDraw, a drawable is drawn using the current Width/Height.
Now if the view is told to change its intrisic size, it will requestLayout. This triggers OnMeasure/OnSizeChanged and finally OnDraw.
It works fine, the drawable is always displayed using the correct inner size.
The problem is, if the new inner size is smaller than the old one, android leaves the old drawing (which seems to be "under" the new one, but in fact should have been cleared by android).
I tryed to clear the view content inside OnDraw, but the drawing rectangle is alread clipped to the new view size.
It sounds like a bug in LinearLayout not clearing its content when a child's view size shrink. Testing on Android 4.4 / Samsung S3 4G / CyanogenMod cm-11-20151004-NIGHTLY.
Layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/content"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000000"
android:padding="8dp">
<LinearLayout
android:orientation="horizontal"
android:id="#+id/content"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:gravity="top">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#CCD39F">
<MyCustomView
android:id="#+id/myview"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
What i see after updating the custom view size. Only the "black part" should be displayed, not the white one.
It should be something like this instead:
I found the problem and a workaround.
The real problem is in LinearLayout. From Android 4.0.3 to Android 6. When this vertical linearlayout has weight=1 and height=0dp, and it has only one child which height is smaller than the available height. The first time this child is drawn, no problem. If the height of this child shrink, the area below it is not repainted. So it stays with the old content of the first child, instead of being refilled with the layout background color.
In the following layout code, i demonstrate the problem and solution. The solution is to add a second child which will take the rest of the free space below the first child. Using this technics it works as expected when the first child shrinks, the second one expands and the newly "empty" space is repainted correctly.
So it is really a bug in LinearLayout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000000">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="top">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#CCD39F">
<MyCustomView
android:id="#+id/icon"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- Solution. To see the problem, remove the following layout -->
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#111111" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="right">
<Button
android:text="Other demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btnNextImage" />
<Button
android:text="Next SVG"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btnGoEmpty" />
</LinearLayout>
</LinearLayout>
I made a compound control, but when i add this new component into a XML layer with other standard components(e.g. TextView), when this layer is inflated, the compound control has a big margin added in the bottom separating this from the others components. I tried adding Layer_bottomMargin = 0dp without success, the only way to resolve this, is adding layer_height a fixed value (i.e. 15dp) instead "wrap_content", but this solution is not fine for me, due i want remove dinamically some component from my compound control.
The code of my compound control:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left|top"
android:clickable="false"
android:background="#CCCCCC"
android:layout_marginTop="#dimen/fieldset_margin"
>
<TextView
android:id="#+id/header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/title_default"
android:textSize="14sp"
/>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#color/fieldset_lines_shadow"
/>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#color/fieldset_lines_light"
/>
</LinearLayout>
And the code of my layer including this compound control:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#C8D5F6FF"
android:gravity="top"
android:layout_margin="8dp"
>
<com.apps.example.Header
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#color/fieldset_text_secondary"
android:text="nananananan"
android:textSize="10sp"
android:layout_marginLeft="#dimen/fieldset_margin"
/>
</LinearLayout>
Sorry but this is my first post and i can't upload images.
Thanks in advance.
I resolved partially by overwriting the onMeasure method in my compound control class. I did not this before because in the official documentation:
http://developer.android.com/guide/topics/ui/custom-components.html
says that is not necessary overwrite this method when is creating a compound control.
Anyway, this is partial solution due when an individual control of the compound is programmatically turned invisible (GONE) occurs the same issue mentioned in the original post but with smaller margin space.
I will continue trying to resolve this, but for now, this is my solution.
Thanks!
I want to design a layout like in this image
Frame 1 is gray and he Frame 2 is transparent. I think we need to use FrameLayout but I don't know exactly how to use it.
Indeed you could use a FrameLayout or a RelativeLayout(at least for the Frame 1) but you don't say what exactly do you want to do with those frames(this will change things a bit). I would use a RelativeLayout because I'm guessing you'll have content in frame 1 besides frame 2:
<RelativeLayout android:id="#+id/frame1" android:background="#c1c1c1"// other attributes>
<FrameLayout android:id="#+id/frame2" android:layout_centerInParent="true"
android:background="#android:color/transparent"// other attributes />
</RelativeLayout>
one way can be:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#c0c0c0" >
<LinearLayout
android:layout_width="200dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:background="#ffffff"
android:gravity="center" >
</LinearLayout>
</RelativeLayout>
You can not make the above like screen using two frames, because it is not possible to put one frame in to the another frame layout, so you can make it by using another way like, take one relative layout and put the frame inside it like,
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/black" >
<FrameLayout
android:id="#+id/frameLayout1"
android:layout_width="250dp"
android:layout_height="100dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="180dp"
android:background="#color/tbl_green">
</FrameLayout>
</RelativeLayout>
may be this can help you.