So, I'm trying to make a login activity with the camera feed as the background. I've tested the example on https://developer.xamarin.com/guides/android/user_interface/textureview/ and got it to work, but I need to it to be part of an activity. So, I tried this:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
SetContentView(Resource.Layout.Login);
_textureView = this.FindViewById<TextureView>(Resource.Id.textureView);
_textureView.SurfaceTextureListener = this;
}
public void OnSurfaceTextureAvailable(
Android.Graphics.SurfaceTexture surface, int w, int h)
{
_cam = Camera.Open();
_textureView.LayoutParameters =
new FrameLayout.LayoutParams(w, h);
try
{
_cam.SetPreviewTexture(surface);
_cam.StartPreview();
}
catch (Java.IO.IOException ex)
{
Console.WriteLine(ex.Message);
}
}
The axml file looks somewhat like this:
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextureView
android:id="#+id/textureView"
android:layout_width="match_parent"
android:layout_height="match_parent"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="SizeProportional" />
<LinearLayout
android:id="#+id/linearLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="SizeProportional">
<!-- Some other controls -->
</LinearLayout>
</AbsoluteLayout>
However, the app now crashes after exiting the OnSurfaceTextureAvailable block, giving an unhandled exception. Breaking at the exception doesn't work, it's apparently in a thread that's not running anymore.
Would anyone know why it crashes and, more importantly, how to fix it?
Problem is with this code:
_textureView.LayoutParameters = new FrameLayout.LayoutParams(w, h);
I'm not sure why your need to reset the TextureView's layout parameters, in xml you've set it to match parent. And the parent here is AbsoluteLayout, not FrameLayout, that's why this error happens.
To solve this issue, since AbsoluteLayout is obsolete now, I suggest to use RelativeLayout as root container in your xml. Then you can code like this:
_textureView.LayoutParameters = new RelativeLayout.LayoutParams(width, height);
Of course you can also change AbsoluteLayout to FrameLayout in your xml, then the code _textureView.LayoutParameters = new FrameLayout.LayoutParams(w, h); doesn't need to be modified anymore.
Related
I'm trying to use PDFTron for Xamarin Android.
I want to render and paint my custom annotations, without using their annotation system.
According to their documentation in https://www.pdftron.com/documentation/xamarin/guides/ui-customization/custom-view/android/ You can add a CustomRelativeLayout which doesn't work.
It basically renders nothing in top of the PDF
I hosted the whole solution in here http://s000.tinyupload.com/index.php?file_id=14574507524295393508 so it's easy to test and see if someone can see what's wrong.
Thanks!
UPDATE
Tried Shirley G suggestion. Modified the pdf_custom_layout to be added to:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="50dp"
android:layout_height="50dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Custom Layout Text View"
android:textSize="24dp"
android:elevation="2dp"/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_red_dark" />
</LinearLayout>
and the code to:
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
private PDFViewCtrl _pdfControl;
private PDFDoc _doc;
protected override void OnCreate(Bundle savedInstanceState)
{
PDFNet.Initialize(this, Resource.Raw.pdfnet, "Insert commercial license key here after purchase");
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
_pdfControl = FindViewById<PDFViewCtrl>(Resource.Id.pdfControl);
var assets = this.Assets;
using var sr = new StreamReader(assets.Open("dummy.pdf"));
_doc = new PDFDoc(sr.BaseStream);
_pdfControl.DocumentLoad += _pdfControl_DocumentLoad;
_pdfControl.SetDoc(_doc);
}
private void _pdfControl_DocumentLoad(object sender, System.EventArgs e)
{
var overlay = new CustomRelativeLayout(BaseContext);
var color = new Android.Graphics.Color(BaseContext.GetColor(Resource.Color.red));
overlay.SetBackgroundColor(color);
overlay.SetZoomWithParent(true);
LayoutInflater.Inflate(Resource.Layout.pdf_custom_layout, overlay);
_pdfControl.AddView(overlay);
}
But nothing happened, still no overlay shown.
UPDATE 2
I added the fixes and started working, however, when I add this code:
var overlay = new CustomRelativeLayout(BaseContext, _pdfControl, 50, 50, 1);
overlay.SetBackgroundColor(BaseContext.Resources.GetColor(Resource.Color.orange));
overlay.SetZoomWithParent(true);
_pdfControl.AddView(overlay);
overlay.LayoutParameters.Width = 300;
overlay.LayoutParameters.Height = 300;
_pdfControl.Invalidate();
overlay.RequestLayout();
I see a small rect of 50x50 at page position x=50 and y50. I specified the overlay to be 300 in width and it's not showing it.
If I add this, nothing is shown at all even the overlay should be of 300x300 at x=0, y =0.
var overlay = new CustomRelativeLayout(BaseContext, _pdfControl, 0, 0, 1);
The layout needs to be added on to the view hierarchy (i.e. PDFViewCtrl.AddView) which is not done in your project. You can find a working sample here:
https://github.com/PDFTron/pdftron-android-samples/tree/master/CustomUI
In particular, relevant code can be find here:
https://github.com/PDFTron/pdftron-android-samples/blob/master/CustomUI/app/src/main/java/com/pdftron/android/tutorial/customui/custom/CustomLinkClick.java
The sample adds the layout to page 3, since your pdf file only have 1 page, you will want to change that to page 1 in the XML layout. Do note that all posX and poxY are in page space, not screen space. Read more on the topic here:
https://www.pdftron.com/documentation/android/guides/basics/coordinates
With that in mind, running your project will see:
layout:
<pdftron.PDF.Tools.CustomRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="50dp"
android:layout_height="50dp"
app:posX="50"
app:posY="50"
app:pageNum="1"
app:zoomWithParent="true">
<!--Child views under CustomRelativeLayout-->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Custom Layout Text View"
android:textSize="12sp"
android:elevation="2dp"/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_red_dark" />
</pdftron.PDF.Tools.CustomRelativeLayout>
If you are adding the view programmatically, you will need to specify the location, or if you are putting it over an annotation, you can specify the annotation.
Typically looks like this:
CustomRelativeLayout overlay = new CustomRelativeLayout(context);
overlay.setBackgroundColor(context.getResources().getColor(R.color.orange));
overlay.setAnnot(pdfViewCtrl, annot, pageNum);
overlay.setZoomWithParent(true);
pdfViewCtrl.addView(overlay);
I am programming a android app with ImageView and when I try to change the width and height dynamically, the app stops (abort). I am using the following commands:
RelativeLayout.LayoutParams icon_horizontal = new RelativeLayout.LayoutParams(50, 50);
mec21h_icon2.setLayoutParams(icon_horizontal);
The layout is Relative, so what is wrong?
It would be nice to have a Stack trace in order to understand what the error is.
Without this, I can just guess:
you're trying to use the wrong parent layout params
the ImageView ref is null
...
I guess you are trying to change the image dimensions after it is visible (already displayed), if so you should first call for method requestLayout();
i.e.
mImageView.requestLayout();
Re-size image on Click of a button.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/rel"
tools:context="com.testingpp.scannerbarcode.MainActivity">
<ImageView
android:id="#+id/imageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:onClick="button_one"
android:src="#drawable/btn_back"
/>
</FrameLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
FrameLayout layout;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageview);
layout = (FrameLayout) findViewById(R.id.rel);
}
public void button_one(View view)
{
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(50,50);
layout.setLayoutParams(params);
}
}
if you are using Framents, then don't use onClick of xml. use onClickListener in java.
I've looked over several SO questions and a couple tutorials.
I have tracked the problem, I think, to the context. The solution appears to possibly be editing my xml file, but nothing I find regarding this helps to remedy my problem.
In my main activity with onCreate I try to acquire a reference of my only text view object. This returns a null reference. How do I obtain a valid reference to the textview which I manually placed? I don't know if I have even added this text view correctly; should I have added it via code or something?
Here are both my onCreate and XML.
protected void onCreate(Bundle savedInstanceState) {
Log.i("[DEBUG]", "main activity - started");
super.onCreate(savedInstanceState);
s_textView = (TextView)findViewById(R.id.textView);
m_GLView = new MyGLSurfaceView(this);
setContentView(m_GLView);
s_textView = (TextView)findViewById(R.id.textView);
Log.i("[DEBUG]", "main activity - finished");
}
I have also tried the following line s_textView = (TextView)m_GLView.findViewById(R.id.textView);
activity_main.xml
<RelativeLayout 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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<merge>
<com.example.a2_1039652.a2_cooper.MyGLSurfaceView />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:textSize="20dp" />
</merge>
</RelativeLayout>
I only have added this <com.example.a2_1039652.a2_cooper.MyGLSurfaceView /> line because it was the solution for a similar problem. It hasn't appeared to change anything about my application.
try this
protected void onCreate(Bundle savedInstanceState) {
Log.i("[DEBUG]", "main activity - started");
super.onCreate(savedInstanceState);
m_GLView = new MyGLSurfaceView(this);
setContentView(m_GLView);
RelativeLayout layout = (RelativeLayout)LayoutInflater.from(this).inflate(R.layout.activity_main,null);
s_textView = (TextView) layout.findViewById(R.id.textView);
Log.i("[DEBUG]", "main activity - finished");
}
So after a few hours of rest I was able to come up with the correct string of words to find a SO question with a solution. The solution was found in the question itself found here: Drawing Android UI on top of GLSurfaceView
I am unclear of whether there is an answer to my question. However for an end result I needed a text view, and now I have one which I can set text on. This is how I did it.
I removed the text view I manually placed. Here is the subsequent activity_main.xml file:
<RelativeLayout 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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
</RelativeLayout>
It is unclear to me how much of that configuration data is needed. Though I removed as much as I could find to be removable.
Next I, for the most part, just took the code line for line from that other SO question. This is what I have for my onCreate method.
protected void onCreate(Bundle savedInstanceState) {
Log.i("[DEBUG]", "main activity - started");
super.onCreate(savedInstanceState);
m_GLView = new MyGLSurfaceView(this);
rl = new RelativeLayout(this);
rl.addView(m_GLView);
tv = new TextView(this);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
lp.addRule(RelativeLayout.CENTER_VERTICAL);
tv.setLayoutParams(lp);
tv.setBackgroundColor(0xFFFFFFFF);
rl.addView(tv);
s_textView = tv;
setContentView(rl);
Log.i("[DEBUG]", "main activity - finished");
}
For now I will mark this as the solution. If someone comes along and provides an answer for how to properly obtain a reference - for a manually added TextView when the app is using a GLSurfaceView - then I will mark it as the answer, so long as it works.
I've got a FrameLayout which I want to grow as time continues.
I've implemented a Runnable-Interface.
public void run() {
time_value++;
FrameLayout fl_dateTime = (FrameLayout)findViewById(R.id.game_DateTime);
LayoutParams lp_fl_dateTime = fl_dateTime.getLayoutParams();
lp_fl_dateTime.width = time_value;
handler.postDelayed(this, 100);
}
Why doesn't this work? O_O
You need to set the layout params back after modifying them.
View#setLayoutParams(ViewGroup.LayoutParams lp)
I was able to do this by setting the initial size of the frame to 0dp and then just setting the minWidth to whatever I wanted.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:background="#android:color/black"
android:id="#id/layout"
android:minHeight="50dp"
android:measureAllChildren="false">
item.setMinimumWidth(10dp);
Let me begin with the coding first.
My xml file (relevant part of it) contains this:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#ffffff">
<SurfaceView
android:id="#+id/cameraView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone" />
<LinearLayout
android:id="#+id/layStatus"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<TextView
android:id="#+id/txtStatus"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#90000000"
android:paddingBottom="5dip"
android:paddingTop="5dip"
android:gravity="center_vertical|center_horizontal"
android:textSize="20dip" />
</LinearLayout>
</FrameLayout>
As you can see I've got a basic set up, a frame layout which contains a surfaceview (which has visibility set to gone) and another layout with a simple TextView.
Here is what I have in my activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
cameraView = (SurfaceView)findViewById(R.id.cameraView);
surfaceHolder = cameraView.getHolder();
surfaceHolder.addCallback(CompassActivity.this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void btnCameraOnClick(View target) {
cameraView.setVisibility(View.VISIBLE);
}
Starting the camera preview is done in Surface changed, which fires when visibility of the surface changes.
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
txtStatus.setVisibility(View.Visible);
txtStatus.setText("Starting camera");
camera = Camera.open();
if (camera != null){
try {
camera.setDisplayOrientation(90);
Camera.Parameters parameters = camera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size size = sizes.get(0);
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
camera.startPreview();
txtStatis.setVisibility(View.GONE);
} catch (IOException e) {
}
}
}
So what's the problem ? I want to simply display a text while the camera preview starts. To do this, I make the txtStatus visible and set a text to it. When the preview is started, I simply hide it. Well, it doesn't work like this, When I press a button to start camera preview, the UI thread freezes waiting for the preview and my status message is not displayed. How can I fix it ? There is a solution at HERE but I was thinking that maybe there is a simpler one.
Thank you for your time.
Camera start up takes some time - external process shall be started and everything set up. I would speculate, that surface changed callback is executed directly from setVisibility() and blocks UI thread. Solution is pretty simple - just spawn new thread and do camera init there.
In my OCR applicatios I start camera in onResume() - since I always need working preview
You may find my OCR android demos helpful:
http://sourceforge.net/projects/javaocr/
( camera preview, with overlays )