Camera SurfaceView flicker in view pager while scrolling - android-layout

In my App I am using ViewPager with FragmentStatePagerAdapter to display 4 different layout.
Layout 1 , 3 , 4 consists of ListView and 2nd layout contains SurfaceView Camera. Now when I am scrolling horizontally camera at the both edges get flicker.
I search on google, and find different solutions. like
1) giving minus margin with android:layout_gravity = "center".
2) viewPager.requestTransparentRegion(viewPager);
Here in first case, it works good at first time but when comming back from resume it cuts from right showing black rectangle.
also I have also tried with different parent layout but the same scenario
happened and also tried to give margin programmatically, but could not find any solution.
Here is my Camera xml.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="#+id/surface_view"
android:layout_width="match_parent"
android:layout_gravity="center"
android:layout_marginRight="-100dp"
android:layout_marginLeft="-100dp"
android:layout_height="match_parent"
android:visibility="visible" />
</LinearLayout>
and here is my fragment adapter.
public class DashboardAdapter extends FragmentStatePagerAdapter {
public DashboardAdapter(FragmentManager fm) {
super(fm);
fragmentList = new ArrayList<>();
fragmentList.add(new InboxFragment());
fragmentList.add(new CameraFragment());
fragmentList.add(new ContactFragment());
fragmentList.add(new AddFriendsFragmnet());
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return InboxFragment.newInstance(position);
case 1:
return CameraFragment.newInstance(position);
case 2:
return ContactFragment.newInstance(position);
case 3:
return AddFriendsFragmnet.newInstance(position);
default:
return CameraFragment.newInstance(position);
}
}
#Override
public int getCount() {
return 4;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
}
Any help would be too much thankful.

I have replaced SurfaceView with TextureView to open a camera.
Link
Here is a link for an example of TextureView Camera. It's working now.
Thanks

Related

Create Android splash screen using SVG animation

I am developing an app using Xamarin.Forms and I am trying to insert the splash screen to my Android project.
I found a few tutorials for creating a splash screen with a background color and a static png image, but I want to use my svg animation as splash screen. I thought I could follow a tutorial for static image and just replace the png image with the svg animation, but it didn't work. Here's what I have so far:
On SplashActivity.cs:
[Activity(Label = "SplashActivity", Theme = "#style/Theme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
}
protected override void OnResume()
{
base.OnResume();
Task startupWork = new Task(() => { SimulateStartup(); });
startupWork.Start();
}
async void SimulateStartup()
{
await Task.Delay(5000);
StartActivity(new Intent(Application.Context, typeof(MainActivity)));
}
}
On MainActivity.cs:
// I only changed the MainLauncher property to false
[Activity(Label = "MyApp", Icon = "#mipmap/icon", Theme = "#style/MainTheme", MainLauncher = false, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
...
}
On styles.xml (in the Xamarin.Android project):
<style name="Theme.Splash" parent="android:Theme">
<item name="android:windowBackground">#drawable/desenhando5s</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="colorPrimaryDark">#004632</item>
</style>
When I run the application, it only shows a black screen as splash screen and then shows my login page as always.
Can anybody tell me what I have to do to set my animation as the splash screen?
(FYI: in case anyone wants to know, I created the animation using SVGator)
You could use FFImageLoading to load your svg image in your SplashActivity instead of set it in styles.xml.
Splash screen:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FFImageLoading.Views.ImageViewAsync
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Code:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
SetContentView(Resource.Layout.layout5);
var filePath = "check";
var imageView = FindViewById<ImageView>(Resource.Id.imageView);
ImageService.Instance.LoadCompiledResource(filePath).WithCustomDataResolver(new SvgDataResolver(64, 0, true)).Into(imageView);
}
protected override void OnResume()
{
base.OnResume();
Task startupWork = new Task(() => { SimulateStartup(); });
startupWork.Start();
}
async void SimulateStartup()
{
await Task.Delay(5000);
StartActivity(new Intent(Application.Context, typeof(MainActivity)));
}
Updated:
Please check the screenshot. The .svg image is in the drawable folder. The layout5 is the splash screen in the layout folder.

cannot find symbol variable imageView2

I am just starting with Android Studio. I got some code from the web on how to ass a splash screen to my app, but it has compiling errors. I could use some help.
the errors are:
error. can not find symbol variable imageView2
error. can not find symbol variable s_img
error. can not find symbol variable s_image_black
error. can not find symbol variable s_image_black
I know this is due to my lack of knowledge, but I am just starting and trying to use this example to learn. Any help would be much appreciated.
Cheers
Paul
package org.quaestio.kotlinconvertedwebview;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.widget.ImageView;
import org.quaestio.kotlinconvertedwebview.MainActivity;
import java.util.Random;
public class Splashscreen extends Activity {
Thread splashTread;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splashscreen);
imageView = (ImageView)findViewById(R.id.imageView2);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
int[] ids = new int[]{R.drawable.s_img,R.drawable.s_image_black, R.drawable.s_image_black2};
Random randomGenerator = new Random();
int r= randomGenerator.nextInt(ids.length);
this.imageView.setImageDrawable(getResources().getDrawable(ids[r]));
splashTread = new Thread() {
#Override
public void run() {
try {
int waited = 0;
// Splash screen pause time
while (waited < 3500) {
sleep(100);
waited += 100;
}
Intent intent = new Intent(Splashscreen.this,
MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
Splashscreen.this.finish();
} catch (InterruptedException e) {
// do nothing
} finally {
Splashscreen.this.finish();
}
}
};
splashTread.start();
}
}
activity_splashscreen below
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#feffc3"
android:layout_gravity="center"
android:id="#+id/lin_lay"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/splash"
android:background="#drawable/splash_img" />
</LinearLayout>
The problem is that you're setting an id wich don't correspond with the xml file. For example imageView = (ImageView)findViewById(R.id.imageView2); you need to change imageView2 with your xml imageview id wich is "splash". For the pthers error you need to check that files in the drawable folder.
Hope it was helpful
The ImageView in your xml has id splash, so in your code, instead of:
imageView = (ImageView)findViewById(R.id.imageView2);
you should do
imageView = (ImageView)findViewById(R.id.splash);
Also, this line:
int[] ids = new int[]{R.drawable.s_img, R.drawable.s_image_black, R.drawable.s_image_black2};
assumes that in your drawable folder there exist all these drawables:
s_img, s_image_black, s_image_black2
but apparently they don't, so you have to copy or create them and put them in the drawable folder.

Custom Drawable not generating round corners for CardView's image

I created a list of Cards with the new CardView and RecyclerView that look this way:
I've tried to modify the card with round corners as explained by Mariotti in this post.
PROBLEM: The problem is that, as you can see from the screenshot I am only able to set the card's corner while the image remains squared.
In the example a custom Drawable class extending Drawable draws a rounded rectangle using Canvas.drawRoundRect(), and use a Paint with a BitmapShader to fill the rounded rectangle with a texture instead of a simple color, as also explained here.
In my Adapter I have:
#Override
public ContactViewHolder onCreateViewHolder(final ViewGroup viewGroup, int i) {
final View itemView = LayoutInflater
.from(viewGroup.getContext())
.inflate(R.layout.item_card_view, viewGroup, false);
CardView cardView = (CardView) itemView.findViewById(R.id.card_view);
ImageView imageView = (ImageView) itemView.findViewById(R.id.hImage);
Bitmap mBitmap = BitmapFactory.decodeResource(itemView.getResources(), R.drawable.background);
//Default
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
//Default
imageView.setBackgroundResource(R.drawable.background);
} else {
//RoundCorners
madapps.hellogridview.RoundCornersDrawable round = new madapps.hellogridview.RoundCornersDrawable(
mBitmap,
itemView.getResources().getDimension(R.dimen.cardview_default_radius)
, 5); //or your custom radius
cardView.setPreventCornerOverlap(false); //it is very important
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
imageView.setBackground(round);
else
imageView.setBackgroundDrawable(round);
}
//Set onClick listener
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int tag = (Integer) v.findViewById(R.id.hTitle).getTag();
Toast.makeText(viewGroup.getContext(), "Clickable card no: "+tag, Toast.LENGTH_LONG).show();
}
});
return new ContactViewHolder(itemView);
}
and I've overridden the value of R.dimen.cardview_default_radiusto 8dp, with no result! Any ideas?
I've solved it using this:
https://github.com/pungrue26/SelectableRoundedImageView
and applying a radius of 10dp (same as the card) to the top corners of the image:
<com.joooonho.SelectableRoundedImageView android:id="#+id/headerImage"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="#drawable/cardbackground3"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
app:sriv_left_top_corner_radius="10dip"
app:sriv_right_top_corner_radius="10dip"
app:sriv_left_bottom_corner_radius="0dip"
app:sriv_right_bottom_corner_radius="0dip"
app:sriv_border_color="#333333"/>
Thanks thats exatly what I need. But you know there is one problem know. There is little space like padding between borders of CardView and Image. But there was no paddings in my case. It seems to mе that this library rounded corners but dont change position of image. Do you have the same think? By the way my layout the same as yours. Do you have any ideas about that?

Best way to create buttons dynamically

I want to create button dynamically in my application. The buttons need to be created based on items fetched from database. What is the best way to achieve this. Should I go for grid layout or Linear layout. My layout is simple with max 3 buttons per row. Once the first row is complete the buttons should be placed in second row.
I scanned lot of similar questions(some had grid layout other were using Linear layout) but unable to decide what is the optimum way to implement this.
I am complete newbie in android application, so any code snippets would be really helpful. Apologies if someone feels this is a duplicate question (I searched a lot before posting but didn't find appropriate answer to layout to be used.)
Thanks.
Please try to use gridView same as bellow code.
// in xml write this code
<GridView
android:id="#+id/calendar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:numColumns="3" />
// grid adapter
public class GridAdapter extends BaseAdapter {
private final Context _context;
private final List<String> list;
public GridAdapter(Context context, ArrayList<String> list) {
super();
this._context = context;
this.list = list;
}
public String getItem(int position) {
return list.get(position);
}
#Override
public int getCount() {
return list.size();
}
public View getView(int position, View convertView, ViewGroup parent) {
Button button = new Button(_context);
button.setText("button" + list.get(position));
return button;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
}
/// in oncreate
gridView.setAdapter(new GridAdapter(getApplicationContext(),list);

Android getMeasuredHeight returns wrong values !

I'm trying to determine the real dimension in pixels of some UI elements !
Those elements are inflated from a .xml file and are initialized with dip width and height so that the GUI will eventually support multiple screen size and dpi (as recommended by android specs).
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="150dip"
android:orientation="vertical">
<ImageView
android:id="#+id/TlFrame"
android:layout_width="110dip"
android:layout_height="90dip"
android:src="#drawable/timeline_nodrawing"
android:layout_margin="0dip"
android:padding="0dip"/></LinearLayout>
This previous xml represent one frame. But I do add many dynamically inside a horizontal layout describe here :
<HorizontalScrollView
android:id="#+id/TlScroller"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_margin="0dip"
android:padding="0dip"
android:scrollbars="none"
android:fillViewport="false"
android:scrollbarFadeDuration="0"
android:scrollbarDefaultDelayBeforeFade="0"
android:fadingEdgeLength="0dip"
android:scaleType="centerInside">
<!-- HorizontalScrollView can only host one direct child -->
<LinearLayout
android:id="#+id/TimelineContent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_margin="0dip"
android:padding="0dip"
android:scaleType="centerInside"/>
</HorizontalScrollView >
The method defined to add one frame inside my java code :
private void addNewFrame()
{
LayoutInflater inflater = (LayoutInflater) _parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.tl_frame, null);
TextView frameNumber = (TextView) root.findViewById(R.id.FrameNumber);
Integer val = new Integer(_nFramesDisplayed+1); //+1 to display ids starting from one on the user side
frameNumber.setText(val.toString());
++_nFramesDisplayed;
_content.addView(root);
// _content variable is initialized like this in c_tor
// _content = (LinearLayout) _parent.findViewById(R.id.TimelineContent);
}
Then inside my code, I try to get the actual real size in pixel because I need this to draw some opengl stuff over it.
LayoutInflater inflater = (LayoutInflater) _parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.tl_frame, null);
ImageView frame = (ImageView) root.findViewById(R.id.TlFrame);
frame.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
frame.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
final int w = frame.getMeasuredWidth();
final int h = frame.getMeasuredHeight();
Everything seems to work fine except that those values are way bigger than the actual pixel size of the ImageView.
Reported infos from getWindowManager().getDefaultDisplay().getMetrics(metrics);
are the following :
density = 1,5
densityDpi = 240
widthPixel = 600
heightPixel = 1024
Now, I know the rule from android is : pixel = dip * (dpi /160). But nothing makes any sense with the value returned. For that ImageView of (90dip X 110dip), the returned values of the measure() method is (270 x 218) which I assumed is in pixel !
Anyone has any idea why ?
Is the value returned in pixel ?
By the way : I've been testing the same code but with a TextView instead than an ImageView and everything seems to be working fine ! Why !?!?
You're calling measure incorrectly.
measure takes MeasureSpec values which are specially packed by MeasureSpec.makeMeasureSpec. measure ignores LayoutParams. The parent doing the measuring is expected to create a MeasureSpec based on its own measurement and layout strategy and the child's LayoutParams.
If you want to measure the way that WRAP_CONTENT usually works in most layouts, call measure like this:
frame.measure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST));
If you don't have max values (for example if you're writing something like a ScrollView that has infinite space) you can use the UNSPECIFIED mode:
frame.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
Do that:
frame.measure(0, 0);
final int w = frame.getMeasuredWidth();
final int h = frame.getMeasuredHeight();
Solved!
Ok ! Kind of Answering my own question here...But not completly
1 - It seems that on some devices, The ImageView measuring do not provide with exact values. I've seen lots of reports on this happenning on Nexus and Galaxy devices for example.
2 - A work around that I've come up with :
Set the width and height of your ImageView to "wrap_content" inside xml code.
Inflate the layout inside your code (generally in the UI initialization I suppose).
LayoutInflater inflater = (LayoutInflater)
_parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.tl_frame, null);
ImageView frame = (ImageView) root.findViewById(R.id.TlFrame);
Calculate your own ratio for your image view, based on the typical Android calculation
//ScreenDpi can be acquired by getWindowManager().getDefaultDisplay().getMetrics(metrics);
pixelWidth = wantedDipSize * (ScreenDpi / 160)
Use the calculated size to set your ImageView dynamycally inside your code
frame.getLayoutParams().width = pixeWidth;
And voila ! your ImageView has now the wanted Dip size ;)
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
//now we can retrieve the width and height
int width = view.getWidth();
int height = view.getHeight();
//this is an important step not to keep receiving callbacks:
//we should remove this listener
//I use the function to remove it based on the api level!
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN){
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}else{
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
One should go with How to get width/height of a View
Unfortunately, in Activity lifecycle methods such as Activity#onCreate(Bundle), a layout pass has not yet been performed, so you can't yet retrieve the size of views in your view hierarchy. However, you can explicitly ask Android to measure a view using View#measure(int, int).
As #adamp's answer points out, you have to provide View#measure(int, int) with MeasureSpec values, but it can be a bit daunting figuring out the correct MeasureSpec.
The following method tries to determine the correct MeasureSpec values and measures the passed in view:
public class ViewUtil {
public static void measure(#NonNull final View view) {
final ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
final int horizontalMode;
final int horizontalSize;
switch (layoutParams.width) {
case ViewGroup.LayoutParams.MATCH_PARENT:
horizontalMode = View.MeasureSpec.EXACTLY;
if (view.getParent() instanceof LinearLayout
&& ((LinearLayout) view.getParent()).getOrientation() == LinearLayout.VERTICAL) {
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
horizontalSize = ((View) view.getParent()).getMeasuredWidth() - lp.leftMargin - lp.rightMargin;
} else {
horizontalSize = ((View) view.getParent()).getMeasuredWidth();
}
break;
case ViewGroup.LayoutParams.WRAP_CONTENT:
horizontalMode = View.MeasureSpec.UNSPECIFIED;
horizontalSize = 0;
break;
default:
horizontalMode = View.MeasureSpec.EXACTLY;
horizontalSize = layoutParams.width;
break;
}
final int horizontalMeasureSpec = View.MeasureSpec
.makeMeasureSpec(horizontalSize, horizontalMode);
final int verticalMode;
final int verticalSize;
switch (layoutParams.height) {
case ViewGroup.LayoutParams.MATCH_PARENT:
verticalMode = View.MeasureSpec.EXACTLY;
if (view.getParent() instanceof LinearLayout
&& ((LinearLayout) view.getParent()).getOrientation() == LinearLayout.HORIZONTAL) {
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
verticalSize = ((View) view.getParent()).getMeasuredHeight() - lp.topMargin - lp.bottomMargin;
} else {
verticalSize = ((View) view.getParent()).getMeasuredHeight();
}
break;
case ViewGroup.LayoutParams.WRAP_CONTENT:
verticalMode = View.MeasureSpec.UNSPECIFIED;
verticalSize = 0;
break;
default:
verticalMode = View.MeasureSpec.EXACTLY;
verticalSize = layoutParams.height;
break;
}
final int verticalMeasureSpec = View.MeasureSpec.makeMeasureSpec(verticalSize, verticalMode);
view.measure(horizontalMeasureSpec, verticalMeasureSpec);
}
}
Then you can simply call:
ViewUtil.measure(view);
int height = view.getMeasuredHeight();
int width = view.getMeasuredWidth();
Alternatively, as #Amit Yadav suggested, you can use OnGlobalLayoutListener to have a listener called after the layout pass has been performed. The following is a method that handles unregistering the listener and method naming changes across versions:
public class ViewUtil {
public static void captureGlobalLayout(#NonNull final View view,
#NonNull final ViewTreeObserver.OnGlobalLayoutListener listener) {
view.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
final ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
viewTreeObserver.removeOnGlobalLayoutListener(this);
} else {
//noinspection deprecation
viewTreeObserver.removeGlobalOnLayoutListener(this);
}
listener.onGlobalLayout();
}
});
}
}
Then you can:
ViewUtil.captureGlobalLayout(rootView, new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int width = view.getMeasureWidth();
int height = view.getMeasuredHeight();
}
});
Where rootView can be the root view of your view hierarchy and view can be any view within your hierarchy that you want to know the dimensions of.
You have to create Custom Textview and use it in your layouts and use getActual height function to set the height at runtime
public class TextViewHeightPlus extends TextView {
private static final String TAG = "TextViewHeightPlus";
private int actualHeight=0;
public int getActualHeight() {
return actualHeight;
}
public TextViewHeightPlus(Context context) {
super(context);
}
public TextViewHeightPlus(Context context, AttributeSet attrs) {
super(context, attrs);
setCustomFont(context, attrs);
}
public TextViewHeightPlus(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
actualHeight=0;
actualHeight=(int) ((getLineCount()-1)*getTextSize());
}
}
Probably, because of what you have in AndroidManifest.xml (link) file and from which drawable-XXX directory the xml file comes, Android loads resources with scaling operation. You decide to use "dip" (link) dimension unit which is virtual and the real value (px) can be different.

Resources