Android: WebView load image/content in center - java

I have loaded an image with WebView but when it is zoomed out max the image place itself in the top left corner of my device. Is there anyway to load the image so it is displayed in center?
Cheers!

I did it with a combination of xml and code. I have my gif file stored in assets folder.
Following is the xml layout code:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<WebView
android:id="#+id/webView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true" />
</RelativeLayout>
Following is the java code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview);
WebView webView = (WebView) findViewById(R.id.webView);
webView.setWebViewClient(new WebViewController());
webView.loadDataWithBaseURL("file:///android_asset/","<html><center><img src=\"animation.gif\"></html>","text/html","utf-8","");
}
private class WebViewController extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}

You can use this code to center the image at the center of the screen in a WebView :
//first you will need to find the dimensions of the screen
float width;
float height;
float currentHeight;
WebView mWebView;
//this function will set the current height according to screen orientation
#Override
public void onConfigurationChanged(Configuration newConfig){
if(newConfig.equals(Configuration.ORIENTATION_LANDSCAPE)){
currentHeight=width;
loadImage();
}if(newConfig.equals(Configuration.ORIENTATION_PORTRAIT)){
currentHeight=height;
loadImage();
}
}
//call this function and it will place the image at the center
public void load and center the image on screen(){
mWebView=(WebView)findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setBuiltInZoomControls(true);
mWebView.setBackgroundColor(0);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
height = displaymetrics.heightPixels;
width = displaymetrics.widthPixels;
currentHeight=height //assuming that the phone
//is held in portrait mode initially
loadImage();
}
public void loadImage(){
Bitmap BitmapOfMyImage=BitmapFactory.decodeResource(Environment.getExternalStorgeDirectory().getAbsolutePath()+"yourFolder/myImageName.jpg");
mWebView.loadDataWithBaseURL("file:///"+Environment.getExternalStorgeDirectory().getAbsolutePath()
+"yourFolder/","<html><center>
<img src=\"myImageName.jpg\" vspace="
+(currentHeight/2-(BitmapOfMyImage.getHeight()/2))+">
</html>","text/html","utf-8","");
//This loads the image at the center of thee screen
}
I have used the center tag to center the image vertically and then used the vspace tag to give image top margin . Now the margin is calculated by : screenVierticalHeight/2-ImageVerticalHeight/2
Hope this helps

mWebView.loadDataWithBaseURL("file:///"+Environment.getExternalStorgeDirectory().getAbsolutePath()+"yourFolder/","<html><center><img src=\"myImage.jpg\"></html>","text/html","utf-8","");
This places image from SDCard at center of the webView. I hope this helps

String html = "<html><head><style type='text/css'>html,body {margin: 0;padding: 0;width: 100%;height: 100%;}html {display: table;}body {display: table-cell;vertical-align: middle;text-align: center;}</style></head><body><p style=\"color:white\">+"you message"+</p></body></html>";
webView.loadData(html, "text/html; charset=UTF-8", null);
So this will load your webview with the text in center

Try to load an HTML file that embeds the image instead. All the layout may done with standard css styles then.

I had the same problem - centering vertically in webview. This solution works most of the time... maybe it can help you a little
int pheight = picture.getHeight();
int vheight = view.getHeight();
float ratio = (float) vheight / (float) pheight;
System.out.println("pheight: " + pheight + "px");
System.out.println("vheight: " + vheight + "px");
System.out.println("ratio: " + ratio + "px");
if (ratio > 0.5)
{
return;
}
int diff = pheight - vheight;
int diff2 = (int) ((diff * ratio) / 4);
if (pheight > vheight)
{
// scroll to middle of webview
currentPhotoWebview.scrollTo(0, diff2);
System.out.println("scrolling webview by " + diff2 + "px");
}

I know this answer's a little late but here's an option without javascript:
you can extend WebView and use the protected methods computeHorizontalScrollRange() and computeVerticalScrollRange() to get an idea of the maximum scroll range and based on that calculate where you want to scrollTo with computeHorizontalScrollRange()/2 - getWidth()/2 and similarly for vertical: computeVerticalScrollRange()/2 - getHeight()/2
my only advice would be to make sure that loading is complete before doing so, i haven't tested if this works while things are loading but i don't think it would as the webview won't yet have it's scroll range correctly set (as content is still being loaded)
see: Android webview : detect scroll where i got a lot of my info from.

For me that is work:
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "PICTURE FILE NAME";
File file = new File(path);
String html = "<style>img{height: 100%;max-width: 100%;}</style> <html><head></head><body><center><img src=\"" + imagePath + "\"></center></body></html>";
webView.getSettings().setDefaultZoom(ZoomDensity.FAR);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.loadDataWithBaseURL( "" , html, "text/html", "UTF-8", "");

Related

RelativeLayout LayoutParams incorrect scaling

I have a Relative Layout within an XML file with an ImageView element which contains both width and height for an image.
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/tankHeight"
android:layout_width="210dp"
android:layout_height="350dp"
android:layout_centerInParent="true"
app:srcCompat="#drawable/tank_progress" />
I then try and dynamically change the height (only height, not width) of the image when the method is called in its class, as follows...
public void updateTank() {
ImageView myTank = (ImageView)findViewById(R.id.tankHeight);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)
myTank.getLayoutParams();
params.height = 350 - 35;
myTank.setLayoutParams(params);
}
However, when this method is called, the image appears to scale by the specified amount in both height and width, when I only want to reduce the height by 35 pixels. My understanding is that this may be due to using a relative layout, but I am not sure how to overcome the issue, so that I can programmatically change the height only. From reading this and this, I had thought the method was set up correctly, so am unsure why it is displaying differently than intended?
The default ScaleType for an ImageView is FIT_CENTER. What this means is that the source image will be scaled so that you can see the entire thing, regardless of the view's aspect ratio... so even though your ImageView is probably only changing its height, the image content is being scaled in both dimensions despite only having the view height change.
Try setting android:scaleType="centerCrop" on your ImageView tag. This will allow you to resize the view without re-scaling the image contents.
More info on scale types: https://robots.thoughtbot.com/android-imageview-scaletype-a-visual-guide
Changing a view height and/or width requires it to be redrawn, try calling requestLayout(). Hope it helps.
public void updateTank() {
ImageView myTank = (ImageView)findViewById(R.id.tankHeight);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)
myTank.getLayoutParams();
params.height = 350 - 35;
myTank.setLayoutParams(params);
myTank.requestLayout();
}
I believe you should first convert dp to pixel.
public int convertDpToPixel(float dp) {
Context context = getContext();
if (context == null) {
return 0; // context should never be a null
}
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
return (int) (dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT));
}
and then you can call
myTank.getLayoutParams();
params.height = convertDpToPixel(350) - convertDpToPixel(35);
myTank.setLayoutParams(params);

Android: Ripple Background Programmatically

I am currently creating an Android app where someone can input their name, press a button, and then it just outputs their name back to them.
One effect that I would like to achieve with this is an effect where, after they push the button, the input and button will vanish (complete this bit so far), and then the background colour of the MainActivity's view will do a ripple (from the centre) with a new colour, eventually changing the full background colour.
How would I go about doing this programatically, since I am only able to find tutorials on adding ripples to buttons when pushed?
EDIT:
I tested this by making a small app
First of all hide the view you want to reveal in this animation.
The view can be from the same layout and in xml its visibility should be invisible so that the animation will reveal it.
You can set the view height and width to match parent if you want to create a full screen animation...
Take your original and reveal view both in frame layout
In my case,I have used this:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:text="Hello World!"
android:layout_width="wrap_content"
android:textSize="20sp"
android:layout_height="wrap_content" />
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimaryDark"
android:id="#+id/revealiew"
android:visibility="invisible"
>
</FrameLayout>
then in your activity on button click or some event do this:
fab.setOnClickListener(new View.OnClickListener() {
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onClick(View view) {
// previously invisible view
View myView = findViewById(R.id.revealview);
// get the center for the clipping circle
int cx = myView.getWidth() / 2;
int cy = myView.getHeight() / 2;
// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
//Interpolator for giving effect to animation
anim.setInterpolator(new AccelerateDecelerateInterpolator());
// Duration of the animation
anim.setDuration(1000);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
}
});
}
You can take detailed look at official documentation here:
http://developer.android.com/training/material/animations.html
What you are describing is a reveal effect on the background.
From the official doc you can find ready to use examples:
1) Here is how to reveal a previously invisible view using reveal effect:
// previously invisible view
View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = myView.getWidth() / 2;
int cy = myView.getHeight() / 2;
// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
2) Here is how to hide a previously visible view using the reveal effect:
// previously visible view
final View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = myView.getWidth() / 2;
int cy = myView.getHeight() / 2;
// get the initial radius for the clipping circle
int initialRadius = myView.getWidth();
// create the animation (the final radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
// start the animation
anim.start();
In you app, you can use a colored background layer (invisible at the beginning) and then use the reveal effect on it.
check this site, "Android Ripple Background" is a library to do it and the min sdk is 11 (Android 3.0 Honeycomb) https://android-arsenal.com/details/1/1107

Add image to location where user click on Layout

I am trying to add image to the point (X,Y) on Layout i have created dynamicaly.
I want to add the imageview on exact user clicked location. But the image is not placed on correct location when clicked.
here is my code
final LinearLayout layoutColumnBoxes = new LinearLayout(getParent());
layoutColumnBoxes.setBackgroundColor(Color.GREEN);
layoutColumnBoxes.setId(counterIdForBoxes);
layoutColumnBoxes.setLayoutParams(layoutParamsColumns);
layoutColumnBoxes.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(getParent(),"Event="+event.getX()+"Event Y = "+event.getY(),Toast.LENGTH_SHORT).show();
return false;
}
});
layoutColumnBoxes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ImageView imageView = new ImageView(getParent());
imageView.setImageResource(R.drawable.crack);
LinearLayout lay = (LinearLayout) view.findViewById(v.getId());
lay.addView(imageView);
// Toast.makeText(getParent(),"Clicked View Id is="+v.getId(),Toast.LENGTH_SHORT).show();
}
});
Please help.
See I know what you're trying to say cause I too had this problem a few months back when developing an application. When you click a point on the screen the position of the imageview is not close to the way you clicked it right?
the things I did were
1) remove the excess space around your image.
This is optional. The only reason I stated this was because it depends on the type of image in your image view cause later you will be placing the image based on the top left corner of the imageview.
2) if your loading the images from the drawable folder make sure that you have the right size image in the right folder. This is IMPORTANT. if you screw up the sizes, android is going to alter the size and location of your images based on when your touch is based on the screen.
3) you need to set the margins of your image view properly. After hours of googling I came up with the following first you'll need to get half the height and width of your imageview, use imageview.getMeasuredHeight() / 2 and imageview.getMeasuredWidth() / 2 (Call these imgH and imgW respectively for explanation purposes)
the later in your OnTouchListener you'll have to set the top left margin of your imageview (the methods vary on the type of layout you use). This is done by setting the top margin at "event.getY - imgH" and the left margin at "event.getX - imgW"
I have an app in the playstore which uses this feature, you can check it here .
I hope this has solved your problem :) if it hasn't then don't hesitate to speak your doubts.
this code work for me:
public class MainActivity extends ActionBarActivity {
float x, y;
RelativeLayout rl;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActionBar().hide();
rl = (RelativeLayout) findViewById(R.id.root_view);
rl.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
// rl.removeView(iv);
x = motionEvent.getX();
y = motionEvent.getY();
setImageLocation(x, y);
//rl.addView(iv);
}
return false;
}
});
}
public void setImageLocation(float x, float y) {
ImageView newImage;
RelativeLayout.LayoutParams newparams;
newparams = new RelativeLayout.LayoutParams(20, 20);
newparams.setMargins((int) (x-rl.getPaddingLeft()), (int) (y-rl.getPaddingTop()), 0, 0);
newImage = new ImageView(this);
newImage.setLayoutParams(newparams);
newImage.setImageResource(R.drawable.clock);
rl.addView(newImage);
}
}
activity_main.xml layout only has one relativeLayout that has full screen size(match parent)

how to change a background color when the soft keyboard is out and change it back when it's in

I'm writing an android view (Android 12).
I have a linearlayout with editText controls on it.
I want to change the linearlayout background image when the soft keyboard is out and change it again when the keyboard is hidden.
I have tried to set a focus listener on each editText, but it won't help.
How can I achieve this?
First, add an id to your layout:
android:id="#+id/view"
So for example:
<LinearLayout
android:id="#+id/view"
android:layout_width="match_parent"
android:layout_height="match_parent" >
Then use this code from this question to determine if the soft keyboard is visible. You should probably put this in your onCreate method.
final View root = findViewById(R.id.view);
root.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = root.getRootView().getHeight() - root.getHeight();
if (heightDiff > 100) { // more than 100 pixels is probably a keyboard
// keyboard is shown
layout.setBackground(getResources().getDrawable(R.drawable.idOfPic));
} else {
// keyboard is not shown
layout.setBackground(getResources().getDrawable(R.drawable.otherPic));
}
}
});
Note depending on your layout (speaking from my own experience), the if (heightDiff > 100) may have to change. It might be if (heightDiff > 150) or something else; the pixel height is arbitrary.
Unfortunately, there is no real way to determine if the soft keyboard is visible (ridiculous). This is the best way it can be done.
try this:
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
heightDiff = convertPixelsToDp(heightDiff , this);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
... do something here
}
}
});
more info in this link and this
for working in all device change heightDiff to dp, and work with that and for changing that use following method:
public static float convertPixelsToDp(float px, Context context){
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return dp;
}

WebView.getContentHeight() always returns 0

I'm attempting to display an HTML string in a WebView named webDescription. Because this HTML can sometimes be lengthy, I want to limit the height of the WebView to a maximum dimension and allow the content to scroll within the view.
I am using the following code to wait until the page finishes loading, check the content height and set the height of the enclosing (parent) TableRow to a maximum of 150.
webDescription.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
// do your stuff here
Log.i("EVENTDETAIL", "Web view has finished loading");
Log.i("EVENTDETAIL", "Description content height: " + view.getContentHeight());
if ( view.getContentHeight() > 150 ) {
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, 150);
view.setLayoutParams(params);
}
}
});
However, view.getContentHeight() always returns 0; thus, the LayoutParams of the parent TableRow never get changed.
Can anyone offer any insight into this and how I might fix my problem? Thanks so much for your consideration.
use this code:
if(view.getHeight()>150)
{
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, 150);
view.setLayoutParams(params);
}
I meant use getHeight() instead of getContentHeight()
I would set the WebView to match_parent and set a maxHeight on the TableRow.

Categories