I need to scroll webview. Thats simple. But when webview is scrolled till end, I want one more view to appear as if webview and that one more view were in single scroll view. How to do that properly?
Consider that its incorrect to put webview inside scrollview.
P.S. In other words, it should look like there is a webview with footer. The footer is regular android view.
A roughly method can be the following: place your UIWebView inside a UIScrollView and set the consentSize according to your needs (ie. at the end of the UIWebView contentSize append another UIView of your choice):
#import "ViewController.h"
#interface ViewController () {
UIScrollView *aScrollView;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
aScrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
[self.view addSubview:aScrollView];
UIWebView *aWebView = [[UIWebView alloc] initWithFrame:self.view.frame];
aWebView.delegate = self;
[aWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.apple.com"]]];
[aScrollView addSubview:aWebView];
}
- (void)webViewDidFinishLoad:(UIWebView *)webview
{
CGFloat yourWebViewContentHeight = [[webview stringByEvaluatingJavaScriptFromString:#"document.body.offsetHeight"] floatValue];
[aScrollView setContentSize: CGSizeMake(aScrollView.frame.size.width, yourWebViewContentHeight + 80)];
UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(0, yourWebViewContentHeight, self.view.frame.size.width, 80)];
aView.backgroundColor = [UIColor redColor];
[aScrollView addSubview:aView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
For more fine grain you have to deal with scrollviewdelegate but this can be a good startpoint.
Just Add Webview in Scroll View it will automatically Disable scroll of WebView, See This Demo
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/svc"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/white">
<WebView
android:id="#+id/wv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" />
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</ScrollView>
Related
I want to integrate a Banner Ad from Ironsource but have some problems to get it working.
This is the documentation, but I have problems to integrate it.
Thay say, that I have to write a bannerContainer, but how do I implement it in my XML-View like my main menu?
For this example to work you are going to need a .xml file, to describe this bannerContainer:
<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=".MainActivity">
<FrameLayout
android:id="#+id/bannerContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:visibility="visible" />
</FrameLayout>
This file is in Project.Android/Resources/xml/bannerContainer.xml
After this, I have to add folowing code to my MainActivity:
protected void onCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
// YOUR OTHER CODE //
// YOUR OTHER CODE //
// YOUR OTHER CODE //
IronSource.Init(this, "YOUR_APP_KEY", IronSource.AD_UNIT.Banner);
FrameLayout bannerContainer = FindViewById<FrameLayout>(Resource.Id.bannerContainer);
IronSourceBannerLayout mBanner = IronSource.CreateBanner(this, ISBannerSize.Banner);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MatchParent,FrameLayout.LayoutParams.WrapContent);
bannerContainer.addView(mBanner, 0, layoutParams);
but at this point
bannerContainer.addView(mBanner, 0, layoutParams);
The bannerContainer throws a NullReferenceException...
And still I dont know how to implement the banner in my "normal" views like in my MainMenu. All this code is in my project.Android, but I have my views in my pcl project, how to get access to the banner in the Android part?
Chris
I am designing an cross-platform app for iOS aswell Android with a shared logic using MVVMCross (5.1.1).
Throughout my app I have a fixed toolbar at the top displaying the current view's title aswell a button. Below the bar the interface is changing from view to view
The Android part:
On Android I created a reuseable layout which I embed in my current layout using include.
In my portable project I have a BaseViewModel which has the properties the reuseable toolbar layout binds to. Every other ViewModel derives from this base class. This way I can have all bindable properties of a displayed screen in one ViewModel without the need of nesting but see for yourself:
activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar_login" />
<RelativeLayout
android:id="#+id/parentLoginLayout"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toolbar">
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
app:MvxBind="Text Pin"
/>
</RelativeLayout>
</RelativeLayout>
toolbar_login.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar_login"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="0dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
android:minWidth="25px"
android:minHeight="25px">
<TextView
app:MvxBind="Click ToolbarMenuCommand"
/>
<!-- some other -->
</android.support.v7.widget.Toolbar>
ViewModels.cs
using System.Threading.Tasks;
using Mobile.Helpers;
using ViewModels.Base;
using MvvmCross.Core.Navigation;
using MvvmCross.Core.ViewModels;
using Plugin.MessageBox;
namespace Mobile.ViewModels
{
public abstract class BaseViewModel : MvxViewModel
{
protected void NavigateToMainView()
{
NavigateTo<MainViewModel>();
}
private readonly IMvxNavigationService _navigationService;
protected BaseViewModel(IMvxNavigationService navigationService)
{
_navigationService = navigationService;
}
public IMvxCommand ToolbarMenuCommand => new MvxCommand(OnMenuButtonClick);
protected abstract void OnMenuButtonClick();
}
public class LoginViewModel : BaseViewModel
{
private bool _menuVisibility;
private string _pin;
public LoginViewModel(IMvxNavigationService navigationService) : base(navigationService)
{
}
public bool MenuVisibility
{
get => _menuVisibility;
set => SetProperty(ref _menuVisibility, value);
}
public string Pin
{
get => _pin;
set => SetProperty(ref _pin, value);
}
protected override void OnMenuButtonClick()
{
MenuVisibility = !MenuVisibility;
}
}
}
The iOS part:
I am not entirely sure how to realise above behavior on iOS. I hope someone has a good idea or a good example project for me which I can take a look at. In general it is no problem to refactorise the ViewModels incase my idea is just not possible at iOS.
A few facts about the iOS project:
I am not using storyboards but single .xib's being independent
from each other
In my .xib's files I use autolayout constraints for positioning and
sizing entirely
A few ideas I already had (cant test them right now):
1. idea:
Create a base .xib with the above bar, the constraints aswell the
outlets
Create each new xib Design based on the previously created file
This would mean I need to adjust every view incase I decide to change something about the toolbar but so far I found no other way to embed a .xib in another .xib without having two different ViewControllers. Also I read that inheritance cause problems with outlets.
2. idea
Each .xib has an empty view at the top which acts as a container for
the toolbar
Have a Base ViewController which constructs the toolbar from code and
adds it as a child to the container view, and binds the properties
from the BaseViewModel
In a previous iOS project I noticed that adding views to the layout can cause problems with autolayout. Probably also a not that good solution?
3. idea
Create a xib with the toolbar and a container below and use it as a master page which would probably mean having a MasterViewModel with the toolbar properties and a nested ChildViewModel.
This is probably the way to go but I have to admit that I have no clue what is the best way to approach it (stil pretty new to iOS and MVVMCross).
Does someone have a few useful hints for me? Thanks a lot!
From what I understood I think you should try to use ScrollView for iOS part and try to imitate the ViewPager's behavior from Android, an example.
I've been seeing an issue in an app I'm working on relating to views being visible when they shouldn't be and I was wondering if anyone had seen similar.
I have a fragment viewed from a viewPager, that fragment has a base layout, in that base layout I include a banner style area with some info in it and a button, the layout is defaulted to GONE in the XML, like this.
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:animateLayoutChanges="true" >
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/usage_swipe_container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:animateLayoutChanges="true"
android:layout_height="match_parent">
<ScrollView
android:id="#+id/usage_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:background="#color/background_colour">
<include layout="#layout/layout_in_question"
android:id="#+id/layout_in_question_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
.... Normal Stuff in layout
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
This view is only set to VISIBLE in very select circumstances. However some users are seeing it outside of those circumstances based on a response from a server call, its a very low percentage of users who are seeing it when they shouldn't ( in the region of 0.001% ), the server team insist its not them so I'm trying to ascertain if there are any known android issue or "hacks" that allow this sort of thing. The App supports API 15 and up and we're currently using support libs 25.3.0.
Has anyone seen behavior like this before? are there developer options on some devices that "show all views" or Modded OS's that allow it?
Edit: While I cant share full code snippets due to NDA, I have 2 locations the view can be enabled, both call the same method.
private View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState)
{
setupBanner();
}
/**
* OTTO event based on server response
*/
#Subscribe
public void receiveEvent(BannerEvent event)
{
setupBanner();
}
public void setupBanner() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (shouldShowBanner()) {
findViewById(R.id.layout_in_question_id).setVisibility(View.VISIBLE);
}
}
});
}
shouldShowBanner returns a boolean which is either true/false depending on what the server responded with.
I need to create a floorplan which can be scrolled and zoomed.Some sections of this plan shall be linked to other activities (ie. kitchen). My idea was to lay a simple button on the kitchen-region. With a click on it you can get to the kitchen activity.
Because of scrolling- and zooming-requirement I created a WebView containing my floorplan:
<LinearLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background"
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=".FloorplanActivity"
xmlns:android="http://schemas.android.com/apk/res/android">
<WebView
android:id="#+id/webViewFloorplan"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
<Button
android:id="#+id/buttonKuehltheke"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</WebView>
</LinearLayout>
But now I'm not able to lay a button on a specific region on the floorplan. The Button always appears in upper left corner of my floorplan.
MainActivity-Code:
WebView wvFloorplan = (WebView) findViewById(R.id.webViewFloorplan);
wvFloorplan.getSettings().setBuiltInZoomControls(true);
wvFloorplan.loadUrl("file:///android_asset/services_plan.png");
What needs to be done to set the button to every postition on my WebView (Floorplan)?
Thx Arne
If you are going to be scrolling and zooming this WebView, the coordinates for the kitchen section are going to be dynamic, so positioning a button over it will be difficult.
I would suggest overriding WebView.shouldOverrideUrlLoading. This way you can use html to create a link to the kitchen activity.
wvFloorplan.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("act:")) {
Intent intent = new Intent( <kitchen activity> );
startActivity(intent);
return true;
}
return false;
}
});
You will have to write an html wrapper around the image to map parts of your images to different links but now the coordinates will be static. Instead of http urls use Href="act:kitchen"
I have a bug with my activity.
I have three view stubs in my linear layout like so -
<ViewStub
android:id="#+id/index_1"
android:layout="#layout/index_edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ViewStub
android:id="#+id/index_2"
android:layout="#layout/index_edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ViewStub
android:id="#+id/index_3"
android:layout="#layout/index_edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
my onCreate conditionally checks what to inflate:
for (int i = 0; i < 3; i++) {
int id = convertIndexToId(i); //will turn i into R.id.index_1
ViewStub stub = findViewById(id);
if (bShouldBeSpinner) {
stub.setLayoutResource(R.layout.index_spinner);
View root = stub.inflate();
Spinner spin = (Spinner)root.findViewById(R.id.my_spinner);
spinner.setAdapter(adapter);
spinner.setSelection(0);
}
else {
stub.setLayoutResource(R.layout.index_edittext);
View root = stub.inflate();
EditText et = (EditText)root.findViewById(R.id.my_edittext);
//et.phoneHome(); just kidding
et.setText(String.valueOf(System.currentTimeMillis()));
}
}
I force bShouldBeSpinner to false. The output of the edittext's is as follows:
1300373517172
1300373517192
1300373517221
However, when I rotate the screen and onCreate is called a second time the output is this:
1300373517221
1300373517221
1300373517221
Initially that made me think you should only inflate the view once, and the heirarchy is kept inbetween onCreate's... however when i only run it the first time the second time no views are shown for the stubs.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Spinner style="#style/SearchInput" android:id="#+id/my_spinner" />
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<EditText style="#style/SearchInput" android:id="#+id/my_edittext" />
</LinearLayout>
I feel the documentation is assuming something that I did not notice or am missing. Does anyone see what I am doing wrong?
EDIT
I added to the view stubs android:inflatedId="index_1_root"... etc
it is the strangest thing, when I add these lines after the for loop:
EditText v = indexRoot1.findViewById(R.id.index_edit_text);
Log.d(TAG, "EditTExt: " + v);
EditText v2 = indexRoot2.findViewById(R.id.index_edit_text);
Log.d(TAG, "EditTExt: " + v2);
the output says (I believe) they are references to different EditTexts.
EditTExt: android.widget.EditText#47210fe8
EditTExt: android.widget.EditText#47212ba8
So they are getting inflated again, but the text is set to what the last edittext was set to on the first pass.
There may be some issues when recreating views of different types with the same id.
ViewStub is replaced by inflated view.
I suggest using
setInflatedId(int inflatedId)
to distinguish inflated views.
Hope that help.
Instead of using ViewStubs, I added an id to the root of those stubs (android:id="index_roots") and used
view.addView( (isSpinner) ?
new Spinner(this) : new EditText(this) );
to fix this problem, I will however not accept this answer right away, I'll allow others to answer using the method I was going for.