I'm creating android app that has table layout for the main activity, and that part works perfectly... Now, the idea was to add another part of an app below the existing components, but now I have to put a tabbed layout there. Well, that part also works perfectly when I try to run just that. But what do I have to do to mix those two in such a way that these two show up one below another on the very same screen.
My main code is:
package my.android;
import android.os.Bundle;
public class MyActivity extends FragmentActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
I have different layout files for all the tabs and I have my TabsActivity class I have created following the tutorial here:
http://thepseudocoder.wordpress.com/2011/10/04/android-tabs-the-fragment-way/
So how do I add some TabsActivity ta object to the MyActivity? And it is important to be below the content of this. Thaks in advance...
Ideally this would be done using nested Fragments, but Android doesn't support that yet. That leaves the deprecated ActivityGroup class. You'll need a top level activity that extends ActivityGroup and launches the two activities.
Here is how you launch the activities and get their views:
final Window w = getLocalActivityManager().startActivity(myTag, myIntent);
final View wd = w != null ? w.getDecorView() : null;
if ( null != wd ) {
wd.setVisibility(View.VISIBLE);
wd.setFocusableInTouchMode(true);
}
// TODO: Attach wd to a ViewGroup.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit: Below is a more complete solution.
This is the layout for the top level activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
</LinearLayout>
Here is the top level class:
public class EmbeddedActivityParent extends ActivityGroup {
private LinearLayout mRootLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mRootLayout = (LinearLayout) findViewById(R.id.root_layout);
// Add embedded status activity.
embedActivity("StatusColumn", new Intent(this, StatusActivity.class));
// Add embedded work activity.
embedActivity("WorkArea", new Intent(this, MainActivity.class));
}
private void embedActivity(String myTag, Intent launchIntent) {
final Window w = getLocalActivityManager().startActivity(myTag, launchIntent);
final View wd = w != null ? w.getDecorView() : null;
if ( null != wd ) {
wd.setVisibility(View.VISIBLE);
wd.setFocusableInTouchMode(true);
mRootLayout.addView(wd);
}
}
}
You can add as many embedded activities as you want. You can even nest embedded activities, but be aware that performance could become a factor. We use this to support a dynamic status column.
Personally, I think there is still a use for the ActivityGroup and hope that Gooogle changes their mind about deprecating it.
Related
I'm starting to learn how to build an Android TV for the first time so I apologize for a likely obvious answer to this question. Basically, I'm trying to replicate how the Android TV Youtube App displays when there is no internet connectivity as shown:
YouTube shows the main fragment (I believe) in the back with no videos, and there seems to be a transparent overlay with an ImageView, TextView, and Button. Once there is internet connectivity and the user taps the Retry button, it loads the video content and the overlay disappears.
I'm trying to achieve this exact same technique, and with internet connectivity, I currently have this:
With no internet connectivity, I'd like to show something similar to how YouTube does.
Here's some of my basic code:
MainActivity.java:
public class MainActivity extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_browse_fragment"
android:name="com.ui.MainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.ui.MainActivity"
tools:deviceIds="tv"
tools:ignore="MergeRootFrame" />
MainFragment.java:
public class MainFragment extends DetailsFragment
{
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
setupUIElements();
setupThings();
}
public void setupThings()
{
if (isOnline() == true)
{
prepareBackgroundManager();
loadRows();
setupEventListeners();
}
else
{
// I don't know what to do here???
}
}
public Boolean isOnline()
{
try
{
Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
int returnVal = p1.waitFor();
boolean reachable = (returnVal == 0);
return reachable;
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
}
Simple, if there's internet connection, I load the videos from online, otherwise, I inform the user like YouTube does.
Where I'm stuck is in the else statement. I'm not sure exactly what to create there to achieve this overlay.
I've looked at some solutions regarding switching fragments here:
Switching between Fragment view
How to switch between fragments during onclick?
However, I'm not sure if, for my purpose, I would need to do this?
Can someone point me in the right direction? I'm not looking to have someone write the whole code exactly like the YouTube app, but I'd like to have a small sample, with just maybe a Button or TextView? This will allow me to follow the structure and modify it to meet my requirements.
Thanks.
You can look at the Leanback Sample app, which contains an example of a BrowseErrorFragment.
To display:
BrowseErrorFragment errorFragment = new BrowseErrorFragment();
getFragmentManager().beginTransaction().replace(R.id.main_frame, errorFragment)
.addToBackStack(null).commit();
So, basically, I have an ImageButton called boutonPortail, and another called logo. Initializing boutonPortail works fine, but when I assign it its listener with boutonPortail.setOnClickListener(boutonPortailListener); the app crashes, and I don't know why at all. It's not a problem with the listener since when I assign it to logo it works just fine. I doubt it is a problem with the XML since I copy/pasted the code of logo.
My app prompts for a password, and if the password is correct it switches to another view with the logo and the boutonPortail. Note that the password prompt view also has the logo.
Is the problem that boutonPortail is not on the main view? I tried assigning the listener after switching views, but it still crashes.
EDIT: After putting the button in the main view, the problem is definitely that the button is not in the main view, when I put it in the main view it works fine. Why does it crashes though?
Also, for some reason I can't manage to change the image of the button with boutonPortail.setImageResource(R.drawable.boutonfermer);. (this doesn't happen when it is in the main view)
onCreate method:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
logo = (ImageButton)findViewById(R.id.logo);
boutonPortail = (ImageButton)findViewById(R.id.boutonPortail);
codeEntered = (EditText)findViewById(R.id.codeEntered);
codeSurNotice = (TextView)findViewById(R.id.codeSurNotice);
//attribute all listeners
logo.setOnClickListener(boutonPortailListener);
codeEntered.addTextChangedListener(textWatcher);
codeEntered.setOnKeyListener(codeEnteredListener);
Method to change view:
void codeCorrect() {
setContentView(R.layout.activity_readytopress);
boutonPortail.setOnClickListener(boutonPortailListener); //this line crashes the app, even if put in the onCreate
}
Listener:
private OnClickListener boutonPortailListener = new OnClickListener() {
#Override
public void onClick(View v) {
boutonState++;
if(boutonState>=4)
boutonState=0;
boutonPortail.setImageResource(R.drawable.boutonfermer);
}
};
XML:
<ImageButton
android:id="#+id/boutonPortail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="40dip"
android:src="#drawable/boutonouvrir"
android:background="#00000000"
style="#00000000"
android:layout_gravity="center"
/>
Here's my full code if you want to test it (note that you'll have to call the codeCorrect() method manually since you don't have access to the bluetooth device I use):
MainActivity.java http://pastebin.com/ZXDahPZ6
activity_main.xml http://pastebin.com/f14cVBKj
activity_readytopress.xml http://pastebin.com/0iZm91eq
boutonouvrir.png http://puu.sh/mLGeU.png
ouvertureencours.png http://puu.sh/mLGfI.png
boutonfermer.png http://puu.sh/mLGe5.png
fermetureencours.png http://puu.sh/mLGgW.png
Thanks :)
You do not have a button with the id boutonPortail in activity_main.xml
It is crashing with a Null Pointer Exception.
You cannot add a listener to a null object.
Here is your relevant code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// On récupère toutes les vues dont on a besoin
logo = (ImageButton)findViewById(R.id.logo);
boutonPortail = (ImageButton)findViewById(R.id.boutonPortail);
So you call setContentView(R.layout.activity_main) and then you call findViewById(R.id.boutonPortail)
The findContentView() will return null, because acitivty_main.xml does not have a view ID of that value. So now boutonPortail is null.
Then you call boutonPortail.setOnClickListener(boutonPortailListener) which will crash with a Null Pointer Exception because boutonPortail is null
So i have a strange issue when trying to retrieve a list of sensors on my application.
Printing to the log works just fine.
When I try to append to a textView, it crashes.
Here is where I am doing the attempted appending:
protected void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.activity_main);
sensorTextView = (TextView) findViewById(R.id.sensorList);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
initialiseAccelerometer();
sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor : sensors) {
Log.d("Sensors", "" + sensor.getName());
sensorTextView.append(sensor.getName());
}
sensorManager.registerListener(
this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
mGestureDetector = new GestureDetectorCompat(this, new LongPressListener());
}
And subsequent error:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example.XXXXXX.XXXXXXXXXXX.MainActivity}:
java.lang.NullPointerException:
Attempt to invoke virtual method
'void android.widget.TextView.append(java.lang.CharSequence)' on a null object reference
And the XML file with correct id:
android:id="#+id/sensorList"
Can anyone point me in the right direction or advise me as to what I'm doing wrong?
activity_main.xml:
<android.support.wearable.view.WatchViewStub
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:id="#+id/watch_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rectLayout="#layout/rect_activity_main"
app:roundLayout="#layout/round_activity_main"
tools:context=".MainActivity"
tools:deviceIds="wear"></android.support.wearable.view.WatchViewStub>
Thanks,
Emmett
This section of the documentation notes some quirks of WatchViewStub. In particular, note the following:
The layouts that you specify for square or round screens are not inflated until WatchViewStub detects the shape of the screen, so your app cannot access their views immediately. To access these views, set a listener in your activity to be notified when the shape-specific layout has been inflated
You are probably trying to set the TextView reference too early, which is why it's null at the point you attempt to append text. If you instead use an OnLayoutInflatedListener as in the sample code below (also from the documentation) to wait until the appropriate round/square layout is inflated, you should find that the reference is initialized properly for both screen types:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wear);
WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
#Override public void onLayoutInflated(WatchViewStub stub) {
// Now you can access your views
TextView tv = (TextView) stub.findViewById(R.id.text);
...
}
});
}
[Note that a colleague of mine has indicated that there is currently a bug that requires you to define the square layout xml attribute and the round layout xml attribute in a specific order for this to work - I don't remember offhand which needs to be first, just a heads-up if you run into problems].
My problem is that i've a tabhost with two tabs.
The first is a listview and the second only have two textviews.
What i want is when i click on an item in the listview on tab one, the array position id (int) should be sent to tab/class two, where there is an array who fetches a text by the position id that was sent.
The switching of tabs is done, but i fail everytime i try to send the position-id.
This is how i send it:
TAB ONE:
//This function is called when i click a listitem
public void setDetails(String Text, long arr_id){
Detail detail = new Detail();
detail.setDetail(); // right now i don't send the parameters because it wont even work with or without it.
}
TAB TWO:
TextView descr;
TextView title;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail);
descr = (TextView)findViewById(R.id.desc);
title = (TextView)findViewById(R.id.title);
}
public void setDetailText(String Text){
descr.setText(Text);
}
public void setDetailTitle(String Text){
title.setText(Text);
}
public void setDetail(){
this.setDetailTitle("example text");
this.setDetailText("example text2");
}
I want to set the text on tab two BEFORE it switch to tab two.
This works if i use SetDetail() and setDetailTitle() in the same tab/class, but not in another.
I've googled my ass off, please help me
i do this in my code using getParent() or getActivity() methods in my TabActivity and inner Activitys, cause if we use a TabActivity (wich subclass the ActivityGroup class) we can obtain the 'TextActivity' using ActivityManager and obtain the activity instance, so, here we can call the setDetail() method, and this will execute before the Activity is showed,
in your ListActivity do something like this
((MyTextActivity)((MyTabActivity)getParent()).getLocalActivityManager().getActivity(ACTIVITY_ID)).setDetail();
this works only if in you start the childs activity within your TabActivity with:
intent = new Intent(ACTIVITY_ID).setClass(this, MyMapActivity.class);
getLocalActivityManager().startActivity(ACTIVITY_ID, intent);
How would I call a method from a different activity?
In my main activity, I have a button that shows a dialog to set the difficulty level of the game.
Then you click start game which starts a new activity containing a view with all the game information.
I need to send the difficulty level chosen to the other activity but cannot seem to figure out how to.
You could put it in the extras with the intent:
Intent StartGame = new Intent(this, StartGame.class);
StartGame.putExtra("difficulty", difficultyLevel);
startActivity(StartGame);
Then in your StartGame.class you can retrive it like this(assuming its a string):
Bundle extras = getIntent().getExtras();
if (extras != null) {
String difficulty= extras.getString("difficulty");
}
Well I don't know how sound my solution is but I created a myApplication class which sub classes the Application class .
This holds the reference to the activity I wanted to call
import android.app.Application;
public class myApplication extends Application {
public PostAndViewActivity pv;
}
When the PostAndViewActivity calls the oncreate is sets the pv to point to itself.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((myApplication) getApplication()).pv = this;
Then when I want to call the method I want I just use code like this:
((myApplication) getApplication()).pv.refreshYourself();
Perhaps a bit hacky but it works.....
I welcome some critisism for this ;-)