How to put GLSurfaceView inside a layout on android - java

I would like to create an app where the glsurfaceview is inside a relative layout together with a listview. While coding, my IDE shows no errors, but once I run the application it just crashes.
main.xml
<?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:gravity="center"
android:orientation="horizontal">
<ListView
android:layout_height="wrap_content"
android:layout_width="100dp"
android:background="#6D6D6D"
android:id="#+id/listObjects"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_centerHorizontal="false"/>
<com.shirofuji.thrrededit.GL_handler
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:orientation="horizontal"
android:id="#+id/gl_layout"
android:layout_alignParentLeft="true"
android:layout_alignEnd="#id/listObjects"/>
</RelativeLayout>
MainActivity
package com.shirofuji.thrrededit;
import android.app.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import android.opengl.*;
public class MainActivity extends Activity
{
GL_handler gl_maineditor;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
gl_maineditor = (GL_handler)findViewById(R.id.gl_layout);
//layout_3d.addView(gl_maineditor);
setContentView(R.layout.main);
}
#Override
public void onResume(){
super.onResume();
gl_maineditor.onResume();
}
#Override
public void onPause(){
super.onPause();
gl_maineditor.onPause();
}
}
GL_handler
package com.shirofuji.thrrededit;
import android.opengl.*;
import android.content.Context;
import android.view.View;
import android.util.*;
public class GL_handler extends View
{
GLSurfaceView mainsurface;
GL_renderer scene_renderer;
public GL_handler(Context ctx,AttributeSet attr){
super(ctx,attr);
mainsurface = new GLSurfaceView(ctx);
scene_renderer = new GL_renderer();
mainsurface.setRenderer(scene_renderer);
}
public void onResume(){
mainsurface.onResume();
}
public void onPause(){
mainsurface.onPause();
}
}

The order of calls in the onCreate() method of the activity is wrong:
gl_maineditor = (GL_handler)findViewById(R.id.gl_layout);
setContentView(R.layout.main);
setContentView() needs to be called before you can get any view with findByViewId(). The sequence should be:
setContentView(R.layout.main);
gl_maineditor = (GL_handler)findViewById(R.id.gl_layout);
With that out of the way, I think there's another aspect where you might be on the wrong track. Unless you have a master plan that is just not visible from the posted code. You're not placing a GLSurfaceView in your layout. The GL_handler you place in the layout derives from a plain View. It has a GLSurfaceView as a member variable, but that alone will not make the GLSurfaceView appear.
Unless you have a good reason, it should be much easier to derive your GL_handler class from GLSurfaceView. This will actually result in a GLSurfaceView that becomes part of your view hierarchy when the layout is inflated.

Related

Making a textview global

I am wondering if there is any way that you can make a textview visible over every screen so that I don't have to individually create a textview on every activity.
I want to do this so I can display my application version on every screen for debugging.
Thank you.
Yes! it is possible.
See you have to add this code.
<include layout="#layout/layout_version"/>
and
public class MainActivity extends BaseActivity {
}
And you will find version text.
Just add this few code.
(1) Create a layout that will represent version text.
layout_version.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" // or match_parent (according to your need)
android:layout_height="wrap_content">
<TextView
android:id="#+id/tvVersion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
... other properties
/>
<!--... other component if required-->
</LinearLayout>
(2) Include this to your activity layout like activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
...>
<include layout="#layout/layout_version"/>
</LinearLayout>
(3) Create a BaseActivity.class or add my code if you have already.
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import com.innovanathinklabs.sample.BuildConfig;
import com.innovanathinklabs.sample.R;
public class BaseActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tvVersion = findViewById(R.id.tvVersion);
if (tvVersion != null) tvVersion.setText(BuildConfig.VERSION_NAME);
}
}
(4) Final step is to extend all your activity by BaseActivity.class.
public class MainActivity extends BaseActivity {
}
That's all!

Retaining Fragment Data

Following my previous post where I asked about implementing parceable objects, the solution I got was to use setRetainInstance(true); method.
#CommonsWare provided me a sample which I modified as follows:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="387dp"
android:layout_height="103dp"
android:text="New Text"
android:id="#+id/textView" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change Text"
android:id="#+id/button"
android:layout_gravity="center_horizontal" />
</LinearLayout>
RotationFragmentDemo.java
package com.rotationfragment;
import android.app.Activity;
import android.os.Bundle;
public class RotationFragmentDemo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This check returns 'null' for the first time when there are no fragments
if (getFragmentManager().findFragmentById(android.R.id.content) == null) {
getFragmentManager().beginTransaction().add(android.R.id.content, new RotationFragment()).commit();
}
}
}
RotationFragment.java
package com.rotationfragment;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class RotationFragment extends Fragment implements
View.OnClickListener {
TextView textView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
// This should help to retain fragment
setRetainInstance(true);
View result=inflater.inflate(R.layout.activity_main, parent, false);
result.findViewById(R.id.button).setOnClickListener(this);
textView = (TextView)result.findViewById(R.id.textView);
return(result);
}
#Override
public void onClick(View v) {
textView.setText("Hello.");
}
}
Upon rotation the text in TextView is not restored.
I know some of you would suggest using parceable writeString parceable method to fix this simple example but I want to know why is the Fragment not retained here using setRetainInstance(true)?
And I don't need to retain a string but Socket, Thread and Activity as in previous post.
See the answer, "onRetainInstance saves the Fragment object, but I still have to rebuild UI in onCreateView", So you have to restore the state of your views manually

type cannot be resolved or is not a field

i have just started building android application. And this error
button cannot be resolved to a type
constantly bugs me. here is the java code
package com.android.revision1;
import android.app.Activity;
import android.os.Bundle;
public class Revision1Activity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button=(Button) findViewByid(R.layout.button1);
}
}
Here is the Xml code
<?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:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button" />
</LinearLayout>
button seems undeclared, so declare that field
private Button button;
or local variable:
Button button=(Button) findViewByid(R.layout.button1);
Assuming your variable is declared and you just aren't showing it, you need to import the Button class. Add the following line next to your other imports:
import android.widget.Button;
You need to declare button as it's currently not declared before being set.
Here is the complete code:
package com.android.revision1;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
public class Revision1Activity extends Activity {
private Button button; // this is what you are missing
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button=(Button) findViewByid(R.layout.button1);
}
}

Methods in extended class are not working

I created a menu, where you can swipe up and down. I created this menu as another activity. Now, I need this menu to be added to on other activities.
Following is the code of my menu(SlidingDrawer)
Java
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class DropDownMenu extends Activity {
private TextView addInquiry, addEvent, additionalInfo, addToContacts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drop_down_menu);
//Intializing instance variables
addInquiry = (TextView)findViewById(R.id.menu_add_inquiry);
addEvent = (TextView)findViewById(R.id.menu_add_event);
additionalInfo = (TextView)findViewById(R.id.menu_additional_info);
addToContacts = (TextView)findViewById(R.id.menu_add_to_contacts);
//Register the Listeners
addInquiry.setOnClickListener(new AddInquiryEvent());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.drop_down_menu, menu);
return true;
}
//Test Button
private class AddInquiryEvent implements OnClickListener
{
#Override
public void onClick(View arg0)
{
// TODO Auto-generated method stub
Intent intent = new Intent(DropDownMenu.this,NewLead.class);
startActivity(intent);
}
}
}
XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<SlidingDrawer
android:id="#+id/SlidingDrawer"
android:layout_width="wrap_content"
android:layout_height="250dip"
android:layout_alignParentBottom="true"
android:content="#+id/contentLayout"
android:handle="#+id/slideButton"
android:orientation="vertical" >
<Button
android:id="#+id/slideButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#android:drawable/bottom_bar" >
</Button>
<LinearLayout
android:id="#+id/contentLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dip"
android:background="#cbcbcc" >
<TextView
android:id="#+id/menu_add_inquiry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="#string/add_inquiry"
android:textColor="#ffffff"
android:clickable="true"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
</SlidingDrawer>
</RelativeLayout>
Following is the Code of the other activity
XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/sales_inqury_main_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".SalesInqury" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:text="#string/sales_inqury"
android:textSize="40sp" />
<include layout = "#layout/activity_drop_down_menu"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
Java
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class SalesInqury extends DropDownMenu {
private ImageView addNewSalesInqury;
private RelativeLayout salesInquryMainLayout;
private TextView testEditSales;
#Override
protected void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sales_inqury);
//Intializing instance variables
addNewSalesInqury = (ImageView)findViewById(R.id.add_new_sales_inqury_btn);
salesInquryMainLayout = (RelativeLayout)findViewById(R.id.sales_inqury_main_layout);
testEditSales = (TextView)findViewById(R.id.testWord);
}
}
But, there is an issue. Even thougn I can open the menu in this other activity, I can't click on it's Buttons (TextViews) and navigate to other activities. Why is this?
I think it's because after you've set a contentView in your DropDownMenu activity and bound the listener to the button, in SalesInquiry you set a different contentView. Although this includes the menu-layout, the Views are created anew, so there's no Listener bound to the button anymore.
A solution would either be to specify the menu callbacks in the layout xml via android:onClick="..." or by having a separate method in DropDownMenu that adds the Listener and that you call from your SalesInquiry class after setting the content view.
Example 1, specifying callback in XML
Add android:onClick="onMenuItemClicked" to menu item TextView
<TextView
android:id="#+id/menu_add_inquiry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="#string/add_inquiry"
android:textColor="#ffffff"
android:clickable="true"
android:onClick="onMenuItemClicked"
android:textAppearance="?android:attr/textAppearanceMedium"/>
Add this method to DropDownMenu class and remove the AddInquiryEvent class and the registering of the listeners.
public void onMenuItemClicked(View view) {
switch (view.getId()) {
case R.id.menu_add_inquiry:
Intent intent = new Intent(DropDownMenu.this,NewLead.class);
startActivity(intent);
break;
case R.id.menu_other:
// handle other menu item
break;
// ... and so on ...
default:;
}
}
Example 2, bind listeners in a separate method
In DropDownMenu move the registering of the Listeners to a separate method:
protected void registerListeners() {
//Register the Listeners
findViewById(R.id.menu_add_inquiry).setOnClickListener(new AddInquiryEvent());
}
Note, that you have to find the view again, as the one kept in the local variable is the wrong one, after SalesInquiry set it's content view.
Call the method in SalesInquiry after setting the content view.
setContentView(R.layout.activity_sales_inqury);
registerListeners();
I'm not sure. but can you please try with extending the DropDownMenu-Activity instead of Activity.
public class NewActivity extends DropDownMenu {
// override which you want to override
}
And make sure DropDownMenu in such a way that you can extends what you want to implements. Hope you have got my point.
Consistency Issue (Recommendation)
There is a HUGE misnomer in your class name, you should NOT call an Activity DropDownMenu.
This is confusing, you should instead call it DropDownActivity or something like that. Also do you really need to use an Activity? You do realize a View can still listen to the click of a button right? Not only an Activity can listen to button clicks. If you encapsulate all of this in a View and have a dedicated listener for that view, then you wouldn't have any need for another Activity.
Possible Solution
It's likely related to the activity/component you have registered to listen to the buttons is not correct. Validate your code so that you can at least get the correct response of the onClick.
The problem is that you are attaching the listener to addInquiry in the DropDownMenu:
//Register the Listeners
addInquiry.setOnClickListener(new AddInquiryEvent());
This listener is not attached to the TextView in the extended class, since the setContentView is called and layout is refreshed.
Possible solution, if you are not using the DropDownMenu activity on its own then simply (remove setContentView):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //in DropDownMenu
// setContentView(R.layout.activity_drop_down_menu);
...
...
Not the best solution but would work.
Update: Better Solution
(1) Let the subclass decide which layout to show. This layout must contain the menu (which is true in your case).
public class DropDownMenu extends Activity {
private TextView addInquiry, addEvent, additionalInfo, addToContacts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
_setContentView();
//Intializing instance variables
addInquiry = (TextView)findViewById(R.id.menu_add_inquiry);
addEvent = (TextView)findViewById(R.id.menu_add_event);
additionalInfo = (TextView)findViewById(R.id.menu_additional_info);
addToContacts = (TextView)findViewById(R.id.menu_add_to_contacts);
//Register the Listeners
addInquiry.setOnClickListener(new AddInquiryEvent());
}
protected void _setContentView() {
setContentView(R.layout.activity_drop_down_menu);
}
...
...
}
#override the _setContentView method so that we do not set the view twice.
public class SalesInqury extends DropDownMenu {
...
...
#Override
protected void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
//Intializing instance variables
addNewSalesInqury = (ImageView)findViewById(R.id.add_new_sales_inqury_btn);
salesInquryMainLayout = (RelativeLayout)findViewById(R.id.sales_inqury_main_layout);
testEditSales = (TextView)findViewById(R.id.testWord);
}
#Override
protected void _setContentView() {
// need to make sure this layout contains the menu (otherwise NullPointerException may arise)
setContentView(R.layout.activity_sales_inqury);
}
}

Can I use setContentView outside the oncreate method?

I have seen many people telling that you can set setContentView outside the oncreate method, but I didn't find anywhere an example. Now when I try to use setContentView, my app just crashes. Here is my source code:
AlarmActivity.java:
package com.alarm.example;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.RelativeLayout;
public class AlarmActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button buton = new Button(this);
buton.setId(101);
buton.setText("New alarm");
buton.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
RelativeLayout layout1 = new RelativeLayout(this);
layout1.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
layout1.addView(buton);
setContentView(layout1);
Button nou =(Button)findViewById(101);
nou.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
New_ala nou1=new New_ala();
nou1.nou_alarma();
}
});
}
}
New_ala.java:
package com.alarm.example;
public class New_ala extends AlarmActivity{
public void nou_alarma() {
setContentView(R.layout.timepicker);
}
}
TimePicker.xml:
<?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:orientation="vertical" >
<TimePicker
android:id="#+id/timePicker"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_alignParentBottom="true">
<Button
android:id="#+id/picker_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Save">
</Button>
<Button
android:id="#+id/picker_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Cancel">
</Button>
</LinearLayout>
</LinearLayout>
On more detail, I can use setContentView(R.layout.timepicker) inside the oncreate method without any problems so the problem is that setContentView isn't working properly inside the New_ala.java class. Can anyone help me?
The code after setting the intent:
AlarmActivity:
package com.alarm.example;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class AlarmActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startActivity(new Intent(this, NewAlarmActivity.class));
}
}
NewAlarmActivity:
package com.alarm.example;
import android.os.Bundle;
public class NewAlarmActivity extends AlarmActivity{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timepicker);
}
}
You can call setContentView any time you are running on the event (UI) thread. Be aware that when you do, any fields you initialized by calling findViewById will need to be reset.
The best way to do that is to have multiple activities: instead of nou1.nou_alarma();, create an intent and start a new activity with the new layout.
startActivity(new Intent(this, NewAlarmActivity.class));
And in the onCreate method of NewAlarmActivity, set the content view to R.layout.timepicker
The setContentView() method can be called only once per activity. If you want to completely change the layout at some point you should either go for ViewFlipper or have 2 layouts in the activity and show only one of them at given time by calling view.setVisibility(View.GONE); and view.setVisibility(View.VISIBLE); respectively.

Categories