Update:
I ended up separating out the video player into a separate activity and layout. I then started this activity using the code below.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startActivityForResult(new Intent(MainActivity.this, VideoActivity.class), VIDEO_PID); //load video
//etc.
}
When the app is loaded, I call this function to kill the Video Activity and bring the main activity to the front:
public void doneLoading() {
finishActivity(VIDEO_PID);
}
I don't know if this is the best way, but it worked.
=======================
What's the easiest way of showing a centered VideoView and then switching to a WebView after the application is fully loaded? I verified that both these views work when included individually in the app. I just want to only show the VideoView when loading, then hide it until the application is closed.
I was looking into ViewPager and ViewFlipper, but I haven't gotten anything working yet. I was going to avoid including them in separate activities. PageViewer seemed to manage the views (meaning allow them to run and init themselves), but not actually display them (all I saw was a black screen). I'm probably missing something.
Would it be easier to start the loading video then start off another activity that initializes the webview, which requests focus and sends a message for the loading video activity to quit after initialization is finished?
My layout is below to give an idea of what I'm using.
Thanks.
P.S. I'm avoiding the use of Fragments for Gingerbread support.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<android.support.v4.view.ViewPager android:id="#+id/view_pager"
android:layout_width="wrap_content"
android:layout_height="0dip"
android:layout_weight="1" >
<VideoView
android:id="#+id/videoview_component"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_gravity="center"
/>
<WebView
android:id="#+id/webview_component"
android:layout_width="fill_parent"
android:layout_height="0dip"
/>
</android.support.v4.view.ViewPager>
</LinearLayout>
Related
I have a two RelativeLayout where I have set their visibility to gone using,
android:visibility="gone"
And then on the root element of the activity which is also a RelativeLayout, I have added this attribute
android:animateLayoutChanges="true"
Here's my activity java code
RelativeLayout rellay1, rellay2;
Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
rellay1 = findViewById(R.id.rellay1);
rellay2 = findViewById(R.id.rellay2);
handler.postDelayed(new Runnable() {
#Override
public void run() {
rellay1.setVisibility(View.VISIBLE);
rellay2.setVisibility(View.VISIBLE);
}
}, 2000);
}
When I run the app, the views get displayed immediately without any wait. If I increase the time to 5s, still same results.
I've looked at the logs when starting the activity and nothing suspicious.
NOTE
When answering questions on SO, I sometimes find it hard to understand the users problem when it's cluttered with XML, so I tried hard to keep my question clean. But that might not be enough to diagnose what's wrong with my code so I'm adding a minimal version of the xml for the parent and two child RelativeLayouts without their contents, just the attributes. If more detail is needed I'd be happy to provide.
<?xml version="1.0" encoding="utf-8"?>
<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:animateLayoutChanges="true"
android:background="#drawable/grad_bg"
tools:context=".LoginActivity">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginRight="40dp"
android:layout_marginLeft="40dp">
<ImageView
android:id="#+id/img_view_logo"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="#drawable/ic_android_black_24dp"
android:adjustViewBounds="true"
android:scaleType="fitCenter"/>
<RelativeLayout
android:id="#+id/rellay1"
android:layout_below="#+id/img_view_logo"
android:layout_width="wrap_content"
android:visibility="gone"
android:layout_height="wrap_content">
</RelativeLayout>
</RelativeLayout>
<RelativeLayout
android:id="#+id/rellay2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:visibility="gone"
android:layout_alignParentBottom="true">
</RelativeLayout>
</RelativeLayout>
From the XML above, you'll see that my intention is to have only the ImageView visible initially and the rest should become visible after 2s.
I have looked similar questions about Handler#postDelayed but the problems are not exactly like mine so the solutions where not applicable.
UPDATE
The only problem here seems to be my lack of proper understanding of the android lifecycle(I'm a beginner here). I carried out an experiment by killing all running apps and tried launching my app again and I saw the animation.
So I guess what was happening here was that, the view had already been created and since my activity was still alive even though I had exited the app, subsequent launches of the App loaded a previously saved instance of the activity and that is why it seemed as if the animation wasn't working.
In the webview.xml, I only have a frame layout as a wrapper for the webView as the following,
<FrameLayout
android:id="#+id/scroll_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
As a little background of the webview, it's basically a mobile web page that displays pictures, and allows for horizontal scrolling(either swiping or clicking the 'next' button). Right now, I'm able to scroll to the next photo via swiping, but once I release my finger, the photo pops back to the original photo. Same thing is happening for clicking next, the screen displays half of the next photo before scrolling back to the previous photo.
I have absolutely no idea why this is happening as I've tried all options with playing with the horizontal scrolling attributes, but it still isn't working. Could anyone who has experienced this provide some insights. Please feel free to let me know what additional info you need.
try using linear layout rather than using frame layout as you have only one child that is webview for the parent layout.
this one works for me :
<?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">
<WebView
android:id="#+id/webview_content"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
I wan't to indicate that my webview is loading in some way. Using the Progressbar seems like a good solution but I am not certain how to properly do this.
By Progressbar I mean a spinning thingie in Android.
This is what I know by now and what I have tried:
I know about onPageStarted(...) and onPageFinished(...) callbacks which you define inside the WebViewClient and then hide or show Progressbar based on calls to those methods. BUT this approach is creating many problems with the HTML page inside the webview. For example when I hide Progressbar HTML elements resize and than go back to their original sizes for a brief moment. This looks really ugly and I don't know why this is happening. I tried putting my Progressbar and webview inside Frame and Relative layout (in order to have the progress cantered) and with both of these I get the above problem. HTML page loading is Javascript heavy since there is http://cubiq.org/iscroll-4 library on it but I doubt it's the problem with the library since the same page loads without strange behaviours when opened in Browser app on the phone.
My main problem is that I don't know how to define a layout containing my Progressbar and webview and avoid strange zoom in/out jumps. That is why I am asking how should one show progress bar correctly over a webview.
EDIT:
This is one of the layouts I tried:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<WebView
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
It's more or less similar with relative layout but I use centerInPerent=true on both axes for the ProgressBar
There's an efficient way to show progress in an activity. If you are using ActionBar, then
you can set an INDETERMINATE progressbar (the spinning one), or a horizontal progressbar (as seen on web browsers like Chrome). To do this you have to set the Window Feature to appropriate values like:
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
OR
requestWindowFeature(Window.FEATURE_PROGRESS);
To set the progress value, do this:
setFeatureInt( Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON);
Then call setProgress(int) whenever you want to change the progress value.
You can controll the visibility of the progressbar using
setProgressBarIndeterminateVisibility(true); //sets it to visible
AND
setProgressBarIndeterminateVisibility(false); //hides the progressbar
FrameLayout is designed to block out an area on the screen to display a single item. Generally, FrameLayout should be used to hold a single child view.
I would use a RelativeLayout :
<?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">
<WebView
android:id="#+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:centerInParent="true" />
</RelativeLayout>
This should work...
I'm facing weird issue of flickering using VideoView. When activity starts, it causes minor flicker of fraction for a second. Then, video starts. It shows 2 black lines on the top and the bottom of the video. See the snap-shot below.
I have tested my application on 2 devices
1) Samsung n-8000(Tablet)
2) Lenovo a-800
video.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:gravity="center">
<VideoView
android:id="#+id/vvSplash"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="#00ffffff">
</VideoView>
</LinearLayout>
Activity code:
private VideoView vd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.video);
vd = (VideoView) findViewById(R.id.vvSplash);
playVideo();
}
private void playVideo() {
Uri uri = Uri.parse("android.resource://" + getPackageName() +"/"+ R.raw.intro);
vd.setVideoURI(uri);
vd.setMediaController(null);
vd.start();
}
Any help would be appreciated. Thank you.
As ridiculous as it sounds, but the answer is here:
VideoView inside fragment causes black screen flicking
SurfaceView flashes black on load
I repeat the solution, kudos to those who found out:
<SurfaceView
android:layout_width="0px"
android:layout_height="0px"
android:visibility="gone" />
It is VERY IMPORTANT that you add the surface view to the root view in your activity, not the immediate parent. Otherwise it won't work.
i also faced same problem but solved it by changing layout parameter of videoview from wrap content to match parent . Also you need to remove the background property of video view from XML. I hope it will work for you
For people in the future: This ugly bug seems to have been resolved in Marshmallow. At my work, we are developing with Xamarin (so, basically, all views are added in programmatically). We have a bunch of test devices, and I was mainly working with a Marshmallow device, so I never noticed this black flicker when building the page I was working on. After finally testing with a Lollipop device, I noticed this flicker.
Unfortunately I do not have a solution. We need our application to be as cross-platform as possible, so using a layout xml is discouraged /sadface.
If your issue is VideoView flickering when the back button is pressed, just set your VideoView visibility to INVISIBLE or GONE in the onBackPressed() method of your Activity before calling the super implementation.
If the user can also leave through the "up" button, intercept android.R.home option item to hide the VideoView.
Here's an example in Kotlin:
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
android.R.id.home -> super.onOptionsItemSelected(item).also {
video_view.visibility = GONE // Hide videoView before leaving to avoid flickering
}
R.id.action_share -> consume { shareVideo() } // Your regular menu options
else -> super.onOptionsItemSelected(item)
}
override fun onBackPressed() {
video_view.visibility = GONE // Hide videoView before leaving to avoid flickering
super.onBackPressed()
}
Just remove the following line from your xml.
android:background="#00ffffff"
It will help you :)
For anyone who's still facing the problem and don't get how to use the above answer.
It simply just copies this code and paste it in the main activity layout that you're using the videoview in under the main (first) layout.
<SurfaceView
android:layout_width="0px"
android:layout_height="0px"
android:visibility="gone" />
in my case
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/Mainframlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/facebookbgcolor" >
<SurfaceView
android:layout_width="0px"
android:layout_height="0px"
android:visibility="gone" />
.....rest of the layout
Adapted the xml-based solution from https://stackoverflow.com/a/27307286/38557 to use Java code instead. Put this in the Fragment's onCreateView(), before inflating the layout:
// Add a SurfaceView to prevent flickering when the video is loaded later.
SurfaceView surfaceView = new SurfaceView(getActivity());
surfaceView.setVisibility(View.GONE);
container.addView(surfaceView, new ViewGroup.LayoutParams(0, 0));
It does the same thing, and can be used when you can't or don't want to change the XMLs.
I am creating an application where each tab has different screens to switch between. Originally I was going to have each tab show a different activity but from what I have read, it seems that is a bad way of doing it.
So I have been using an xml file which has the layout for each screen all in the one file. And I use Java to program which to display each screen required and hide the ones I don't need. The problem I have with this approach is it means all my Java is one file, and all my XML is in one file. Could someone explain to me a better way of doing this as I am pretty sure there must be a better way. My activity has many screens and its getting an eye sore scrolling through all this code at once, as the more screens I add, the larger the code is getting.
Ideally I would like to have the code for each screen in its own Java class, and the layouts for each screen in their own xml files and just switch between these.
To give you example of my code
<TabHost android:id="#+id/tabhost" android:layout_width="fill_parent"
android:windowSoftInputMode="adjustResize"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#92c223" android:layout_height="fill_parent">
<LinearLayout android:id="#+id/tab1"
android:layout_above="#android:id/tabs" android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ScrollView android:layout_width="fill_parent"
android:layout_height="wrap_content">
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content">
XML CODE FOR LAYOUT GOES IN HERE. EACH NEW SCREEN IS CONTAINED WITHIN THESE LAYOUTS.
</RelativeLayout>
</ScrollView>
</LinearLayout>
<TabWidget android:layout_width="fill_parent" android:id="#android:id/tabs" android:layout_weight="0"
android:layout_gravity="bottom" android:layout_height="wrap_content"></TabWidget>
</FrameLayout>
</TabHost>
Then in my Java code, I switch between tabs using
if ("home".equals(tabId)) {
tab1.setVisibility(View.VISIBLE);
tab2.setVisibility(View.GONE);
tab3.setVisibility(View.GONE);
tab4.setVisibility(View.GONE);
tab5.setVisibility(View.GONE);
and when switching between screens within an activity, when user clicks a button in that activity, I use on click listener and do this
tab2.setVisibility(View.GONE);
cvv.setVisibility(View.VISIBLE);
I am sure there is a better way of doing this, and would be grateful if someone would give me suggestions.
Another problem is, as its all in one activity, whenever I hit the back button, it just exits the application. Would prefer to have it so when they hit back, it goes back to previous screen.
The 'better way' is giving each tab an activity of its own. Why did you dismiss this approach in your first paragraph? This is exactly what a TabHost was designed for.
What I usually do is subclass TabActivity. In its onCreate(Bundle savedInstanceState) method, I do the following once for each tab:
tabHost.addTab(
tabHost.newTabSpec("tab1")
.setIndicator("Tab 1", res.getDrawable(R.drawable.tab1))
.setContent(new Intent().setClass(this, Tab1Activity.class))
);
Then you develop each Tab#Activity in an independent file. It's nice and modular. Switching between tabs is handled by the library. You don't need to worry about all that.
Within your tabs, you can capture the back button by overriding the onKeyDown method in your inner activity:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// Do your thing
return true;
}
return super.onKeyDown(keyCode, event);
}