getMeasuredHeight() and width returning 0 after measure() - android

I'm really confused with this whole measuring thing that android does for layouts. Basically, I want to get the actual computed height and width of a view when it has been laid out BEFORE it gets laid out. I need to get the computed height and width because I have a hidden LinearLayout that I want to animate when opening using viewpropertyanimator. I need to supply the target width (which is the computed width) to the animator before it animates it. The width of this layout is dynamic because it relies on its android:weight parameter for the width, so I can't give a static value.
Here's my activity class:
package com.example.testproject;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
public class TestActivity extends Activity
{
private LinearLayout gmailListContainer, yahooMailListContainer, windowsLiveListContainer;
private LinearLayout emailMessageContainer;
private Display display;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_test);
gmailListContainer = (LinearLayout) this.findViewById(R.id.email_activity_gmail_layout);
yahooMailListContainer = (LinearLayout) this.findViewById(R.id.email_activity_yahoo_mail_layout);
windowsLiveListContainer = (LinearLayout) this.findViewById(R.id.email_activity_windows_live_layout);
emailMessageContainer = (LinearLayout) this.findViewById(R.id.email_activity_email_content_layout);
gmailListContainer.setBackgroundColor(Color.CYAN);
yahooMailListContainer.setBackgroundColor(Color.MAGENTA);
windowsLiveListContainer.setBackgroundColor(Color.GREEN);
emailMessageContainer.setBackgroundColor(Color.RED);
display = getWindowManager().getDefaultDisplay();
setMeasuredDimensions();
}
private void setMeasuredDimensions()
{
View v = this.findViewById(R.id.email_activity_layout);
v.measure(display.getWidth(), display.getHeight());
Log.v("EmailActivity", v.getMeasuredHeight() + ", " +v.getMeasuredWidth());
}
private void setWeight(LinearLayout container, float weight)
{
LinearLayout.LayoutParams params = (LayoutParams) container.getLayoutParams();
params.weight = weight;
container.setLayoutParams(params);
container.setVisibility(View.VISIBLE);
}
}
Here's the relevant layout resource:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/email_activity_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:baselineAligned="false">
<LinearLayout
android:id="#+id/email_activity_gmail_layout"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<LinearLayout
android:id="#+id/email_activity_yahoo_mail_layout"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<LinearLayout
android:id="#+id/email_activity_windows_live_layout"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<LinearLayout
android:id="#+id/email_activity_email_content_layout"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="0"
/>

Add the below method to your Activity and call your method from it.
#Override
public void onWindowFocusChanged(boolean hasFocus) {
setMeasuredDimensions();
super.onWindowFocusChanged(hasFocus);
}
In onCreate() you can't assure that your view is drawn. It might take some time. But this above method gets called only when the view is drawn completely. So YOu should be able to get the width and height exactly here.

Related

How to fit all elements in gridview in the whole display?

I am new in android and want to create a gridview with some elements (element with Text and Image) and was guided by this link https://www.viralandroid.com/2016/04/android-gridview-with-image-and-text.html.
I have a layout for the activity screen:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/home_screen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<GridView
android:id="#+id/grid_view_image_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="110dp"
android:numColumns="3"/>
</LinearLayout>
the layout for the gridview with text and image:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/android_custom_gridview_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="#+id/android_gridview_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginTop="15dp" />
<TextView
android:id="#+id/android_gridview_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textSize="25sp" />
</LinearLayout>
This is my code:
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
public class HomeScreenActivity extends AppCompatActivity {
private GridView androidGridView;
private String[] gridViewString = {
"Anlagenübersicht", "Instandhaltungsaufträge", "Handlungsleitfaden",
"Wiki", "Historie", "Fehlerdatenbank",
"Wartungsprotokoll", "Ersatzteile", "Werkzeugkasten",
"Remotezugriff", "Personal", "Über uns"
} ;
private int[] gridViewImageId = {
R.drawable.icons8_roboter_48, R.drawable.icons8_bestellung_48, R.drawable.icons8_aufgabenliste_48,
R.drawable.icons8_doktorhut_48, R.drawable.icons8_vergangenheit_48, R.drawable.icons8_datenbank_40,
R.drawable.icons8_wartung_48, R.drawable.icons8_ersetzen_48, R.drawable.icons8_werkzeugkasten_48,
R.drawable.icons8_assistent_48, R.drawable.icons8_gruppe_vordergrund_ausgewaehlte_48, R.drawable.icons8_ueber_48,
};
#Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_screen);
CustomGridViewActivity adapterViewAndroid = new CustomGridViewActivity(HomeScreenActivity.this, gridViewString, gridViewImageId);
androidGridView= (GridView) findViewById(R.id.grid_view_image_text);
androidGridView.setAdapter(adapterViewAndroid);
androidGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int i, long id) {
Toast.makeText(HomeScreenActivity.this, "GridView Item: " + gridViewString[+i], Toast.LENGTH_LONG).show();
}
});
}
}
But my Output is:
But I want that all elements will fill the display in height and with, that there will be no space like you can see here:
Finally, I found a solution from this link:
android How to stretch rows in the gridview to fill screen?
I had to set some attributes for my activity class, and use this:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels;
int height = metrics.heightPixels;
to determine the height and width.
After that, I had to set the Minimum with and height for my View.
For more informations, I recommend you to check the link above. :)

is there a way to dynamicaly add a widget on top of another widget

i'm trying to create a widget called DecoView dynamicaly every time i press a button.
if i just put two deco views in the XML i can see them both and they both look fine on ontop of the other.
but when i try to add it dynamicly in the code, i only create the first one,
and all the rest just aren't get created
what am i missing here ?
can someone help me with this ?
my mainActivity.java
package com.example.shay_v.dynamicdecoviewexample;
import android.graphics.Color;
import android.graphics.PointF;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.hookedonplay.decoviewlib.DecoView;
import com.hookedonplay.decoviewlib.charts.SeriesItem;
import com.hookedonplay.decoviewlib.events.DecoEvent;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button mainMenuButton;
int widgetInteger = 1;
LinearLayout ll;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//pointing to display
mainMenuButton = (Button) findViewById(R.id.button);
mainMenuButton.setOnClickListener(this);
//points to the linear layout in the xml
ll = (LinearLayout)findViewById(R.id.mainMenu_mainLayout);
}
private void createDecoViewWidget (int i) {
//adds params to the linear layout
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
//deco view widget
DecoView decoViewWidget = new DecoView(this);
//adding to view
decoViewWidget.setId(i);
ll.addView(decoViewWidget, params);
//decoViewWidget.configureAngles((int) (Math.random() * 360) + 1, (int) (Math.random() * 100));
//Create data series track
SeriesItem seriesItem = new SeriesItem.Builder(Color.argb(255, (int) (Math.random()*255), (int) (Math.random()*255), (int) (Math.random()*255)))
//third controller is end point
.setRange(0, 100, 0)
.setLineWidth(60f)
.setInset(new PointF(120f, 120f))
.build();
int series1Index = decoViewWidget.addSeries(seriesItem);
decoViewWidget.addEvent(new DecoEvent.Builder((float) (Math.random() * 100)).setIndex(series1Index).setDelay(1000).build());
}
//button listener
#Override
public void onClick(View v) {
createDecoViewWidget (widgetInteger);
widgetInteger++;
}
}
my activity_main.xml >
<?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: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="com.example.shay_v.dynamicdecoviewexample.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<LinearLayout
android:orientation="vertical"
android:layout_width="350dp"
android:layout_height="350dp"
android:layout_centerVertical="true"
android:id="#+id/mainMenu_mainLayout"
android:layout_centerHorizontal="true"></LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="#+id/button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
anyone ?
When you are creating the Views they are being added into a LinearLayout. This type of layout will position the views one after the other, so the second view is being drawn off the visible area of the screen.
As you want all views to be drawn on top of each other you should use a RelativeLayout.

Horizontal scrollview indicator android

I am using Horizontal Scrollview in android to show buttons in my app (i need to use horizontal scrollview.)
By calling some method of srollview, i want to force it to change imageView's background color(or drawable).
here is my sample code.
activity_main (i've set scrollbars="none")
<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=".MainActivity">
<HorizontalScrollView
android:scrollbars="none"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/buttonContainer"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</LinearLayout>
</HorizontalScrollView>
<LinearLayout
android:id="#+id/indicatorContainer"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
</RelativeLayout>
MainActivity
import android.graphics.Point;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Display;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
LinearLayout buttonContainer, indicatorContainer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* getting display size */
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
/* set button size */
int buttonWidthSize = (int) (width / 2.5);
int buttonHeightSize = (int) (height / 5.0);
buttonContainer = (LinearLayout)findViewById(R.id.buttonContainer);
indicatorContainer = (LinearLayout)findViewById(R.id.indicatorContainer);
for(int i = 1; i <= 10 ; i++){
Button button = new Button(this);
button.setText("button"+i);
button.setWidth(buttonWidthSize);
button.setHeight(buttonHeightSize);
buttonContainer.addView(button, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
// how it can be solved.
}
so that,
How can I set indicator(they will just imageviews with canvas). is this possible?
thanks

how to center webview contents in android

SCREENSHOT:
https://camo.githubusercontent.com/7c4b76724b703bcded8aafbba9c012542726462c/687474703a2f2f692e696d6775722e636f6d2f716375554d664a2e706e6725374275726c253744
Hi, is there a way I can center the text and the image of the articles?
this is the layout file:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ptr="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:gravity="center">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text=""
android:textSize="20sp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold" />
</RelativeLayout>
<ScrollView
android:id="#+id/sv"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#id/header" >
<LinearLayout
android:id="#+id/lin"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical" >
<WebView
android:id="#+id/desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:scrollbarStyle="insideOverlay"
android:text="#string/desc" />
</LinearLayout>
</ScrollView>
</RelativeLayout>
Java Code
package com.iven.lfflfeedreader.mainact;
import com.iven.lfflfeedreader.R;
import com.iven.lfflfeedreader.domparser.RSSFeed;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.widget.ScrollView;
import android.widget.TextView;
public class ArticleFragment extends Fragment {
private int fPos;
RSSFeed fFeed;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fFeed = (RSSFeed) getArguments().getSerializable("feed");
fPos = getArguments().getInt("pos");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater
.inflate(R.layout.article_fragment, container, false);
TextView title = (TextView) view.findViewById(R.id.title);
WebView wb = (WebView) view.findViewById(R.id.desc);
ScrollView sv = (ScrollView) view.findViewById(R.id.sv);
sv.setVerticalFadingEdgeEnabled(true);
// Set webview settings
WebSettings ws = wb.getSettings();
ws.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
// Set the views
title.setText(fFeed.getItem(fPos).getTitle());
wb.loadData(fFeed.getItem(fPos).getDescription(), "text/html; charset=utf-8", "UTF-8");
return view;
}
}
the source code of the app is available here
thanks
https://github.com/enricocid/lffl-feed-reader
Try,
wb.getSettings().setDefaultZoom(ZoomDensity.FAR);
This will zoom out and fit the image to your screen and show it in center.
Note: Because the WebView is used to render the scripts and show it in a view, so as long as the source of the web url isn't aligned in center you can't change it. However you can parse the web content and then show them in any customizable way you want.
So far the the github project you are talking about also used the same approach. A html parser called Jsoup was used to parse the html contents and showing in a view.
I've solved my problem by adding
// set image scale to fit screen if larger than screen width
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager wm = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(displayMetrics);
int screenWidth = displayMetrics.widthPixels; // minus some padding values if you have any left/right padding
Drawable drawable = getResources().getDrawable(R.id.image);
int wi = drawable.getIntrinsicWidth();
double scale = (wi>screenWidth) ? (double)screenWidth/wi : 1.0;
wb.setInitialScale((int) (scale*340));'code'
now the image is at the center below the abstract and on top of the article entry...:) gonna push changes later on git. thanks anyway:)

How to find the layout width and height while the activity is loading?

In my app,I should find width and height of a frame layout at the time of activity is loading.When i tried this,i am getting null pointer exception displaying width and height must be greater than zero.Please help me how to find width and height of frame layout in my xml.Thanks in advance.
my main Activity is
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
public class MainActivity extends Activity {
ImageView image;
FrameLayout frame;
int width,height;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
image=(ImageView)findViewById(R.id.imageView2);
frame=(FrameLayout)findViewById(R.id.frame);
frame.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener(){
#Override
public void onGlobalLayout() {
width=frame.getWidth();
height = frame.getHeight();
frame.getViewTreeObserver().removeGlobalOnLayoutListener( this );
}
});
Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
Bitmap scaled=Bitmap.createScaledBitmap(bitmap, width, height, true);
image.setImageBitmap(scaled);
image.setOnTouchListener(new myTouchListener());
}
}
and my main xml is
<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:background="#android:color/black"
android:orientation="vertical"
android:weightSum="3"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="vertical"
android:id="#+id/top_linear"
android:layout_weight="1"
>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="380dp"
android:id="#+id/frame"
>
<ImageView
android:id="#+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:scaleType="matrix"
/>
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="36dp"
android:orientation="horizontal"
android:background="#android:color/black"
android:id="#+id/bottom_linear">
</LinearLayout>
</LinearLayout>
Move your code for the Bitmap handling into the block of the ViewTreeObeserver. Before this code block will be executed the width and height are 0.
frame.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener(){
#Override
public void onGlobalLayout() {
width=frame.getWidth();
height = frame.getHeight();
Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
Bitmap scaled=Bitmap.createScaledBitmap(bitmap, width, height, true);
image.setImageBitmap(scaled);
image.setOnTouchListener(new myTouchListener());
frame.getViewTreeObserver().removeGlobalOnLayoutListener( this );
}
});
getWidth() and getHeight() methods return 0 when layouts width and height are set like match_parent and wrap_content. dimensions are not measured.
The right methods to access to get measured dimensions are getMeasuredWidth() and getMeasuredHeight().
The Correct way:
FrameLayout frmlayout = (FrameLayout)findViewById(R.id.svtest);
ViewTreeObserver vto = frmlayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
scrollView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = frmlayout.getMeasuredWidth();
int height = frmlayout.getMeasuredHeight();
}
});

Categories

Resources