Why does minHeight attribute not work in WebView Android? - java

This question has already been asked here, but it has no solution.
I have a WebView. I want to set minimum height to the WebView using minHeight attribute, but it doesn't work. The same attribute works for Button.
<?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"
tools:context="com.example.anshul.webview.WebActivity">
<WebView
android:id="#+id/webView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="400dp"></WebView>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:minHeight="150dp"
android:text="This is a Button. It's minHeight is set to 150 dp and it works !!"/>
Clearly from the below image, the WebView is not supporting the minHeight attribute. Does anybody knows a solution for this problem?

First, let's understand how other view's use android:minHeight attribute. Let's take Spinner for example. In AbsSpinner#onMeasure() code we see following chunk of code:
...
preferredHeight = Math.max(preferredHeight, getSuggestedMinimumHeight());
preferredWidth = Math.max(preferredWidth, getSuggestedMinimumWidth());
heightSize = resolveSizeAndState(preferredHeight, heightMeasureSpec, 0);
widthSize = resolveSizeAndState(preferredWidth, widthMeasureSpec, 30);
setMeasuredDimension(widthSize, heightSize);
...
So, getSuggestedMinimumHeight() should be regarded when computing preferred height.
Now, let's see how WebView is being measured.
WebView#onMeasure() delegates the job to WebViewChromium#onMeasure()
WebViewChromium#onMeasure() delegates the job to AwContents#onMeasure()
AwContents#onMeasure() delegates the job to AwLayoutSizer#onMeasure
AwLayoutSizer is the last component that is responsible for measuring WebView and we can clearly see, that its onMeasure() does not respect getSuggestedMinimumHeight() value.
I'm not sure whether this is an intended behavior or no. Nevertheless, I cannot find enough seams to somehow affect that measurement process. Here's the chuck of code in WebView class, where the object that eventually would return WebViewChromium (the first step in abovementioned order) is initialized.
private void ensureProviderCreated() {
checkThread();
if (mProvider == null) {
// As this can get called during the base class constructor chain, pass the minimum
// number of dependencies here; the rest are deferred to init().
mProvider = getFactory().createWebView(this, new PrivateAccess());
}
}
As you can see, this is not something that can be easily customized/changed.

Try it :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView)findViewById(R.id.webView);
webView.loadDataWithBaseURL(null, "<html><body bgcolor=\"#E6E6FA\"> hehehe </body></html>", "text/html", "utf-8", null);
}
<?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:background="#color/blue"
android:layout_height="match_parent">
<LinearLayout
android:minHeight="300dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
>
<WebView
android:id="#+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:minHeight="150dp"
android:text="This is a Button. It's minHeight is set to 150 dp and it works !!"/>
</RelativeLayout>

I think webview dimensions work more according to content view port properties...
Check https://developer.android.com/guide/webapps/targeting.html#Viewport
The viewport is the area in which your web page is drawn. Although the viewport's total visible area matches the size of the screen when zoomed all the way out, the viewport has its own pixel dimensions that it makes available to a web page. For example, although a device screen might have physical a width of 480 pixels, the viewport can have a width of 800 pixels. This allows a web page designed at 800 pixels wide to be completely visible on the screen when the viewport scale is 1.0. Most web browsers on Android (including Chrome) set the viewport to a large size by default (known as "wide viewport mode" at about 980px wide). Many browsers also zoom out as far as possible, by default, to show the full viewport width (known as "overview mode").

use constraint layout .that will help to resolve all these types of errors and very easy to use.
if your android studio version is below 2.3.1 then add this dependency.
compile 'com.android.support.constraint:constraint-layout:1.0.0-beta1'

Related

How do I make the foreground attribute for a button work below API 23?

I have two Buttons nested in a LinearLayout. Between these Buttons are two TextViews. In the Xml, I have set the foreground to an image for each of these Buttons.
It runs fine on my device for Api 23. But on other devices below Api 23, the foreground image does not display and instead results in a default white solid color. Is there any way to make these images show using foreground below Api 23?
We have tried FrameLayout but it does not do what we want it to do. Would ImageButtons be a better way to solve this issue?
One of the core functions of our app is that every time a user taps a Button, the size increases and the image stretches accordingly. This is done dynamically in code. If I were to use ImageButtons, I would need to set the layout parameters every time for height and width, rather than one line of code that sets the height.
Any tips would be appreciated!
EDIT: Code I am working with -
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="11"
android:background="#android:color/black">
<Button
android:layout_weight="5"
android:id="#+id/firstP"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:foreground="#drawable/icebutton"
android:scaleX="1"
android:scaleY="1"/>
<TextView
android:layout_weight="0.5"
android:id="#+id/firstPlayer"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:rotation="180"
android:textColor="#android:color/white"
android:background="#android:color/transparent"/>
<TextView
android:layout_weight="0.5"
android:id="#+id/secondPlayer"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:background="#android:color/transparent"/>
<Button
android:layout_weight="5"
android:id="#+id/secondP"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:foreground="#drawable/firebutton"
android:scaleX="1"
android:scaleY="1"/>
</LinearLayout>
We found out that there were two issues causing the images to not be shown.
1. The size of the image file was too big, creating an outOfMemory error which in turn resulted in the buttons not displaying the images.
2. The foreground attribute does not work for API 22 and below.
Steps to solving these issues:
1. We reduced the size of the image files.
2. We replaced Button with ImageButton
3. In the XML file we removed the foreground attribute, added a black background, and added the image via the src attribute. The following is a snippet.
<ImageButton
android:layout_weight="5"
android:id="#+id/firstP"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:src="#drawable/icebutton"
android:scaleType="fitXY"
android:background="#android:color/black"/>
We then had to change our code to dynamically adjust the height of the buttons to match the new image buttons with the help of this link by setting the LayoutParams:
how to change size of button dynamic in android
Now everything works perfectly!

i Can't Resize Image in XML Android

Why I can't display images in a large size, its results even smaller, is there something wrong with my XML code? or errors are in the java code? And i have "[Accessibility] Missing contentDescription attribute on image" on my XML code in ImageView
This my code :
Detail.xml
<ImageView
android:id="#+id/ivPosterImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:adjustViewBounds="true"
android:maxHeight="300dp"
android:src="#drawable/large_movie_poster" />
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ivPosterImage"
android:layout_marginTop="10dp" android:id="#+id/scrollView1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
</ScrollView>
Activity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_box_office_detail);
// Fetch views
ivPosterImage = (ImageView) findViewById(R.id.ivPosterImage);
....
Picasso.with(this).load(movie.getLargePosterUrl()).
placeholder(R.drawable.large_movie_poster).
into(ivPosterImage);
Please help me ...
Its clearly looking that your downloaded image have very small height and width dimension and you have settled the dimension around wrap_content. That's why you are getting this small icon instead of full image.
And again image download libs always use image attribute setSource in their code, which also set image around wrap_content.
Now you have 2 choice to show image wider:
set width = match parent,
height = fixed(any value as per your choice like 100 dp ,200 etc), i have not fixed the width because thats goona create exception on small or large screns.
set image background instead of image src that is by default set by image download libs.
Hopefully this will resolve your issue.

android disable webview bounces

I have set a LinearLayout with admob and WebView.
When admob appears on top, WebView Y pos is properly repositioned to 0 + adMobHeight.
Then if you touch and drag WebView, you are able to move vertially same admob height! This property on iOS is called bounces.
How to deactivate it?
If not possible, hot to force WebView to recalculate its size whitout reloading content? Thank you
Please note that scrolls are alreary disabled,
webviewB.setVerticalScrollBarEnabled(false);
webviewB.setHorizontalScrollBarEnabled(false);
If you always want to display on top of the screen then you may want to consider using RelativeLayout.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.admob.android.ads.AdView
android:id="#+id/ad"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:backgroundColor="#000000"
app:primaryTextColor="#FFFFFF"
app:secondaryTextColor="#CCCCCC"
android:layout_alignParentTop="true"
/>
<!-- WebView below that -->
<!--WebView-->
</RelativeLayout>

AdMob stealing 3 pixels?

I have this layout
<LinearLayout android:id="#+id/mainlayout" android:orientation="vertical" android:layout_height="fill_parent" android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads">
<ScrollView android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1">
<TableLayout android:id="#+id/tableLayout1" android:layout_width="fill_parent" adroid:layout_height="wrap_content" android:gravity="center_horizontal" >
...
...
</TableLayout>
</ScrollView>
Ad is added as follow
LinearLayout mainLayout = (LinearLayout)findViewById( R.id.mainlayout );
AdView adView = new AdView(...);
LinearLayout.LayoutParams llParam = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,nearLayout.LayoutParams.WRAP_CONTENT);
llParam.gravity = Gravity.CENTER_HORIZONTAL ;
mainLayout.addView(adView, llParam);
I really can't figure out why there 3 pixels below the ad (shown as thiny white checkers in the image). I think tehre is no doubt about that, but I added the black and white pattern in the image to highlight the region I'm talking about. In the original it is all black.
IIRC, a number of ad companies add these "pixels" to their image to keep ad distributors honest, as it were.
A number of companies sell this service (example): they give you one-pixel images to add to your advertisements, and then they can track (independently of AdMob) the number of people who loaded your ad by counting the number of times their 1x1 pixel was requested. So this way, an advertiser can make sure that AdMob isn't inflating the number of views of the ad to get more money out of the advertiser.
This might not be the reason in your particular case -- but it sounds like a reasonable explanation.

Android overlay a view ontop of everything?

Can you overlay a view on top of everything in android?
In iPhone I would get the new view set its frame.origin to (0,0) and its width and height to the width and height of self.view. Adding it to self.view would then cause it to act as an overlay, covering the content behind (or if it had a transparent background then showing the view behind).
Is there a similar technique in android? I realise that the views are slightly different (there are three types (or more...) relativelayout, linearlayout and framelayout) but is there any way to just overlay a view on top of everything indiscriminately?
Simply use RelativeLayout or FrameLayout. The last child view will overlay everything else.
Android supports a pattern which Cocoa Touch SDK doesn't: Layout management.
Layout for iPhone means to position everything absolute (besides some strech factors). Layout in android means that children will be placed in relation to eachother.
Example (second EditText will completely cover the first one):
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/root_view">
<EditText
android:layout_width="fill_parent"
android:id="#+id/editText1"
android:layout_height="fill_parent">
</EditText>
<EditText
android:layout_width="fill_parent"
android:id="#+id/editText2"
android:layout_height="fill_parent">
<requestFocus></requestFocus>
</EditText>
</FrameLayout>
FrameLayout is some kind of view stack. Made for special cases.
RelativeLayout is pretty powerful. You can define rules like View A has to align parent layout bottom, View B has to align A bottom to top, etc
Update based on comment
Usually you set the content with setContentView(R.layout.your_layout) in onCreate (it will inflate the layout for you). You can do that manually and call setContentView(inflatedView), there's no difference.
The view itself might be a single view (like TextView) or a complex layout hierarchy (nested layouts, since all layouts are views themselves).
After calling setContentView your activity knows what its content looks like and you can use (FrameLayout) findViewById(R.id.root_view) to retrieve any view int this hierarchy (General pattern (ClassOfTheViewWithThisId) findViewById(R.id.declared_id_of_view)).
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id = "#+id/Everything"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- other actual layout stuff here EVERYTHING HERE -->
</LinearLayout>
<LinearLayout
android:id="#+id/overlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right" >
</LinearLayout>
Now any view you add under LinearLayout with android:id = "#+id/overlay" will appear as overlay with gravity = right on Linear Layout with android:id="#+id/Everything"
You can use bringToFront:
View view=findViewById(R.id.btnStartGame);
view.bringToFront();
The best way is ViewOverlay , You can add any drawable as overlay to any view as its overlay since Android JellyBeanMR2(Api 18).
Add mMyDrawable to mMyView as its overlay:
mMyDrawable.setBounds(0, 0, mMyView.getMeasuredWidth(), mMyView.getMeasuredHeight())
mMyView.getOverlay().add(mMyDrawable)
I have just made a solution for it. I made a library for this to do that in a reusable way that's why you don't need to recode in your XML. Here is documentation on how to use it in Java and Kotlin. First, initialize it from an activity from where you want to show the overlay-
AppWaterMarkBuilder.doConfigure()
.setAppCompatActivity(MainActivity.this)
.setWatermarkProperty(R.layout.layout_water_mark)
.showWatermarkAfterConfig();
Then you can hide and show it from anywhere in your app -
/* For hiding the watermark*/
AppWaterMarkBuilder.hideWatermark()
/* For showing the watermark*/
AppWaterMarkBuilder.showWatermark()
Gif preview -
I have tried the awnsers before but this did not work.
Now I jsut used a LinearLayout instead of a TextureView, now it is working without any problem. Hope it helps some others who have the same problem. :)
view = (LinearLayout) findViewById(R.id.view); //this is initialized in the constructor
openWindowOnButtonClick();
public void openWindowOnButtonClick()
{
view.setAlpha((float)0.5);
FloatingActionButton fb = (FloatingActionButton) findViewById(R.id.floatingActionButton);
final InputMethodManager keyboard = (InputMethodManager) getSystemService(getBaseContext().INPUT_METHOD_SERVICE);
fb.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// check if the Overlay should be visible. If this value is false, it is not shown -> show it.
if(view.getVisibility() == View.INVISIBLE)
{
view.setVisibility(View.VISIBLE);
keyboard.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
Log.d("Overlay", "Klick");
}
else if(view.getVisibility() == View.VISIBLE)
{
view.setVisibility(View.INVISIBLE);
keyboard.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
bringToFront() is super easy for programmatic adjustments, as stated above. I had some trouble getting that to work with button z order because of stateListAnimator. If you end up needing to programmatically adjust view overlays, and those views happen to be buttons, make sure to set stateListAnimator to null in your xml layout file. stateListAnimator is android's under-the-hood process to adjust translationZ of buttons when they are clicked, so the button that is clicked ends up visible on top. This is not always what you want... for full Z order control, do this:

Categories

Resources