Black screen after loading SceneView, using Scenform, into a fragment - android

I am working on a project that will have a 3D model viewer in one fragment. In order to do so, I decided to use sceneform. I have encountered a problem with SceneView, after trying to display it, in my tab fragment.
Everything is done according to examples and sceneform documentation, but sceneView display black screen, regardless of the colour I am assigning.
Here is scene loader
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
vw = inflater.inflate(R.layout.fragment_open_gl, container, false);
sceneView = vw.findViewById(R.id.scene_view);
return vw;
}
And fragment :
<?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="match_parent"
android:layout_height="match_parent"
tools:context=".OpenGL">
<com.google.ar.sceneform.SceneView
android:id="#+id/scene_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/Crimson"/>
</FrameLayout>

I solved the issue by adding pausing and resuming sceneview, along with the fragment:
#Override
public void onPause() {
super.onPause();
sceneView.pause();
}
#Override
public void onResume() {
super.onResume();
try {
sceneView.resume();
} catch (CameraNotAvailableException e) {
e.printStackTrace();
}
}

Related

Android views in fragments overlapping

So I've read several tutorials and many of the posts on SO but I still can't get this to work. I'm trying to use dynamically added fragments but when loading a fragment TextViews and ImageViews in the fragment keep overlapping instead of updating their values, like so:
and fragments overlap each other when replaced.
I got a main activity (extending AppCompatActivity) split into 2 layouts:
<LinearLayout 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/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background_white"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/upperFrameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/lowerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
The upper FrameLayout contains my fragments. The fragments are replaced in this method in the MainActivity-class:
void setMode() {
// Show "find opponent"- or "fight"-fragment
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
if (!debugFight && (btCoordinator == null || !btCoordinator.isConnected())) {
fragmentTransaction.replace(R.id.upperFrameLayout, new FindOpponentFragment());
} else {
fragmentTransaction.replace(R.id.upperFrameLayout, new FightFragment());
}
fragmentTransaction.commitNow();
}
What am I missing?
EDIT: Added FightFragment onCreateView()-method:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
((TextView) inflater.inflate(R.layout.fragment_fight, container, false).findViewById(R.id.score_textView)).setText(getString(R.string.score, 0, 0));
((TextView) inflater.inflate(R.layout.fragment_fight, container, false).findViewById(R.id.opponent_textView)).setText(MainActivity.opponentName.toUpperCase());
final AnimatedVectorDrawableCompat animated = AnimatedVectorDrawableCompat.create(container.getContext(), R.drawable.loading_animated_vector);
animated.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
#Override
public void onAnimationEnd(Drawable drawable) {
animated.start();
}
});
((ImageView) inflater.inflate(R.layout.fragment_fight, container, false).findViewById(R.id.opponent_hand_imageview)).setImageDrawable(animated);
animated.start();
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_fight, container, false);
}
...and as I pasted this piece of code I just realised that those inflated views are all different objects. I replaced them with a single object which I modify and then let the method return and it works. I guess I have to read up on views and the inflate-method.
use fragmentTransaction. add() instead of replace()
Use this above the fragment commit
fragmentTransaction.addToBackStack(null);
I didn't understand how the inflate-method. I modified my fragments onCreateView-method as seen in the OP and now it works.

Android adding a Fragment in project for Facebook Login

So, I'm following the steps in the Android API to add login to my app. My app is already fairly developed, and of course I'm no to android, so I'm having issues at this point.
the step reads:
Then set up the button in your UI by adding it to a fragment and update your activity to use your fragment.
I've searched for how to add a fragment and anything about that, watched youtube videos, but can't find out exactly what this means. Can anyone dumb this down for me?
https://developers.facebook.com/docs/facebook-login/android
First, you need a hosting activity, extending AppCompatActivity that has a FrameLayout in its related layout file. Then you inflate the layout in the onCreate method and add the needed Fragment:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.fragment_placeholder) != null) {
if (savedInstanceState != null) {
return;
}
// we are extending AppCompatActivity, so we need supportFragmentManager
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_placeholder, new ContentFragment()).commit();
}
}
}
The according layout file activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>`
Now you need to define ContentFragment:
public class RecordFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.fragment_content, container, false);
}
}
The last step is the layout file for our fragment, fragment_content, containing a Button:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
For more information why we use AppCompatActivity, read this answer.

Disabling progress bar when URL fetch completes: A standard scenario

I have a rather popular scenario in which there is a fragment containing a progress bar and a ListView. I'd like to populate the ListView after fetching the data using Retrofit. Now, the progress bar needs to be made invisible once a response comes back in.
Would it be a good idea to store the view of the fragment layout inflated in onCreateView() as a member variable and use that variable to disable the progress bar in onResponse() (the callback is created in onCreate()), when the fetch succeeds?
Fragment layout:
<?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:id="#+id/source_items_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp">
<com.gc.materialdesign.views.ProgressBarCircularIndeterminate
android:id="#+id/progress_bar"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="#1E88E5"
android:layout_gravity="center_horizontal"/>
<ListView android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/source_list"/>
</FrameLayout>
onCreate():
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mItemList = new ArrayList<SourceItem>();
RestClient.get().getSources().enqueue(new Callback<SourceItemList>() {
#Override
public void onResponse(Response<SourceItemList> response, Retrofit retrofit) {
if (response.isSuccess()) {
disableProgressBar();
//...
}
}
#Override
public void onFailure(Throwable t) {
disableProgressBar();
return;
}
private void disableProgressBar() {
if (mView != null) {
mView.findViewById(R.id.progress_bar).setVisibility(View.INVISIBLE);
}
}
});
// ...
}
onCreateView():
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_sourceitem_list, viewGroup, false);
// ...
return mView;
}
Thanks
It is better to have progress bar initialized in onCreateView() rather than using view.findViewById() as it's an expensive operation.

How to remove black cover on top of sliding menu?

In my application i have a sliding menu which has been developed by jfeinstein10.
It's working fine in my application ;)
I have a Fragment which is host of MapView. This fragment like my other fragments extended from Fragment class. Just in this Fragment, there is black cover/layer on top of menu contents when I open sliding menu. There is no black cover when I open menu in other fragments. Also, the thing that I found is height of box is exactly as same height as fragment.
Have you seen this problem before? any comments or suggestion would be appreciated.
=>
Update
Based on what Selei suggested I set background to transparent. However, regardless of what color I'm assigning (transparent or other colors) it's still visible and black :(
This is my code:
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
map:uiCompass="true"
android:background="#00000000"/>
The solution was adding map:zOrderOnTop="true" to XML.
For more info please refer to this link.
I tried all the methods here but none of them worked great. Using the GoogleOptions to move the zOrder to the top meant the basic zoom controls were hidden behind the map.
The last suggestion at this link: https://github.com/jfeinstein10/SlidingMenu/issues/168#issuecomment-17065660 (ckakei) fixed it for me.
The trick is to add an empty, transparent view to the layout:
<?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" >
<FrameLayout
android:id="#+id/view_map"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent" />
I'm inflating this view then in a Fragment. I replace the view_map FrameLayout with the SuppportMapFragment.
This is the important part from that class:
private GoogleMap googleMap;
private SupportMapFragment mapFragment;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.view_map_layout, container,
false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
FragmentManager fm = getChildFragmentManager();
if (mapFragment == null) {
mapFragment = SupportMapFragment.newInstance();
}
if (savedInstanceState == null) {
mapFragment.setRetainInstance(true);
} else {
googleMap = mapFragment.getMap();
}
fm.beginTransaction().replace(R.id.view_map, mapFragment).commit();
}
set the MapView background transparent - android:background="#00000000"
I just made map copy view which copy the map when the sliding menu open or close
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
private void showMapCopy(boolean show) {
View map = findViewById(R.id.map);
View mapCopy = findViewById(R.id.map_copy);
if (show) {
map.setDrawingCacheEnabled(true);
Bitmap bitmap = map.getDrawingCache();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
mapCopy.setBackgroundDrawable(new BitmapDrawable(getResources(), bitmap));
else
mapCopy.setBackground(new BitmapDrawable(getResources(), bitmap));
mapCopy.setVisibility(View.VISIBLE);
} else {
map.setDrawingCacheEnabled(false);
mapCopy.setVisibility(View.GONE);
}
}
Sliding Menu Open Listener
mMenu.setOnClosedListener(new OnClosedListener() {
#Override
public void onClosed() {
showMapCopy(false);
}
});
OnOptionItemSelected
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.abs__home:
case android.R.id.home:
showMapCopy(true);
mMenu.toggle();
return true;
default:
return super.onOptionsItemSelected(item);
}
}

Activity with fragments crashes like if it were nested fragments

I guess everybody knows the project that is created when you choose "master detail flow" when creating your project in eclipse.
Theres layouts for the left side, for the right side and a two_pane layout with a fragment and a Framelayout as a fragment container. This works fine.
Now I have a 'main' activity A with a viewpager, fragments etc., and i call the activity from a fragment with the Callback. From that activity A I start a new activity B. That activity B is set up exactly like that example activity from eclipse that I just talked about.
Now I have the problem that the app crashes with
ERROR/AndroidRuntime(8105): Caused by: java.lang.IllegalArgumentException: Binary XML file line #57: Duplicate id 0x7f080024, tag null, or parent id 0x0 with another fragment for FragmentNumber3
When I replace the fragment in the two_pane layout with another framelayout, it doesn't crash.
This problem is typical for nested fragments, but I don't have nested fragments here, right? I have an activity B that, at that point, doesn't have anything to do with my activity A.
What's the problem here?
Edit: This is my Activity B:
public class SucheActivity extends FragmentActivity implements
SearchboxFragment.SearchboxListener {
private boolean mTwoPane;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.searchbox);
getActionBar().setDisplayHomeAsUpEnabled(true);
if (findViewById(R.id.searchresult_container) != null) {
mTwoPane = true;
}
}
}
And thats the two_pane layout for the activity, the searchbox should be left, the searchresults right:
<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:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
android:showDividers="middle" >
<fragment
android:id="#+id/searchbox_fragment"
android:name="com.example.layouttest.SearchboxFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<FrameLayout
android:id="#+id/searchresult_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
Heres the SearchboxFragment class:
public class SearchboxFragment extends Fragment {
SearchboxListener mCallback;
View v;
public interface SearchboxListener {
public void onSearchStarted();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
v = inflater.inflate(R.layout.searchbox, container, false);
return v;
}
}
The searchresultfragment:
public class SearchResultFragment extends Fragment {
public SearchResultFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.searchresult, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
And the refs.xml in res/values-large:
<resources>
<item name="searchbox" type="layout">#layout/haussuche_twopane</item>
</resources>
Okay, so this is what I found out:
I cant set the layout of my Activity to searchbox.xml (and have it alias'd in refs.xml with two_pane.xml) AND set the Layout of SearchboxFragment to searchbox.xml.
I thought that searchbox.xml was never shown by the Activity in two-pane-mode, I could safely set it elsewhere, but that's wrong.
What I did was copy that layout and use a searchbox_onepane.xml and searchbox_twopane.xml.

Categories

Resources