The app I am working on will have 2 displays. Using the DisplayManager I am casting my presentation to a second screen.
I want to find a way to set the orientation of my presentation class to landscape and my activity class to portrait. Code bellow called onCreate of activity to render the presentation.
#Override
protected void onCreate(Bundle savedInstanceState) {
// Get the display manager service.
mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE);
Display[] presentationDisplays = mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
if (presentationDisplays.length > 0) {
mProductPresentation = new ProductPresentation(this, presentationDisplays[0], product);
mProductPresentation.show();
Log.d(TAG, " on display #" + presentationDisplays[0].getDisplayId() + ".");
}
}
The code works perfectly and the display gets rendered correctly. I just want to know if its possible to flip the orientation of the presentation class without changing the orientation of the activity
I ended up just grabbing the layout and rotating it. See code below
#Override
protected void onCreate(Bundle savedInstanceState) {
// Be sure to call the super class.
super.onCreate(savedInstanceState);
//Assign the correct layout
mViewLayout = getLayoutInflater().inflate(R.layout.presentation_product_details, null);
setContentView(mViewLayout);
//We need to wait till the view is created so we can flip it and set the width & height dynamically
mViewLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener());
}
private class OnGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener{
#Override
public void onGlobalLayout() {
//height is ready
mViewLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int width = mViewLayout.getWidth();
int height = mViewLayout.getHeight();
mViewLayout.setTranslationX((width - height) / 2);
mViewLayout.setTranslationY((height - width) / 2);
mViewLayout.setRotation(90.0f);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( height, width);
// Inflate the layout.
setContentView(mViewLayout, lp);
findViews();
}
}
Related
I have created a custom ViewGroup ReadPage, and in activity I use it
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
pager=(ReadPage)findViewById(R.id.readpage);
pager.addArticle("...");
}
While the addArticle need the view's width and height
public void addArticle(String s){
articles.add(new Article(s,getMeasuredWidth(),getMeasuredHeight()));
}
But the measurewidth and measureheight is 0 at that time.
So I want to know at which state the view will be measured so I can get the right value it show in screen.
This answer probably gives you what you need: https://stackoverflow.com/a/1016941/213528
You would maybe use it like this:
private int WIDTH;
private int HEIGHT;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
WIDTH = size.x;
HEIGHT = size.y;
pager = (ReadPage)findViewById(R.id.readpage);
pager.addArticle("...");
}
// ...
public void addArticle(String s){
articles.add(new Article(s, WIDTH, HEIGHT));
}
Use ViewTreeObserver
viewToMeasure.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
viewToMeasure.getViewTreeObserver().removeGlobalOnLayoutListener(this);
/* you can get the view's height and width here
using viewToMeasure.getWidth() and viewToMeasure.getHeight()
*/
}
});
Views are measured sometimes later, during a "measure pass". When View structure changes (due to adding , removing, updating a view), a measure and then a layout pass runs that re-calculates the View sizes and locations.
For example, you can set text data to a TextView any time, but the View itself decides how to display it, when it is ready to display it. The text warp etc is calculated then, and not while setting the text.
You should design the View displaying the Article to be similar. You can provide the data, but let View process and display it further when its onSizeChanged() is called. Views can also employ addOnLayoutChangeListener() to know when layout has been done.
I have tried to create a dialog that occupies the full screen width from the old AlertDialog builder to the new DialogFragment approach in the onCreateView() and onViewCreated() to get the displayed dialog to occupy the full width of the screen. I can certainly get the width and height values of the screen but regardless of how I try to force the dialog to use these values, they are ignored. The displayed dialog is always the same width regardless of orientation.
In my latest attempt I have an xml layout that I inflate. I need to use a custom view so I cannot define that view in xml. So I add it.
Here is the most current attempt I have in my DialogFragment code. Of course this is just one of many attempts I have made trying to follow hints from posts and Slidenerd videos.
public class PopupDialog extends DialogFragment implements View.OnClickListener
{
private static final String TAG = PopupDialog.class.getName();
Button cancel = null;
Button focus = null;
View viewInput = null;
int width;
int height;
int id;
public PopupDialog()
{
}
public PopupDialog(View v, int id, int width, int height)
{
viewInput = v;
this.id = id;
this.width = width;
this.height = height;
}
#Override
public View onCreateView(LayoutInflater inflator, ViewGroup container, Bundle savedInstance)
{
Log.d(TAG, "onCreateView of DialogFragment called.");
View viewDialog = inflator.inflate(R.layout.popup_dialog, null);
// RelativeLayout relativeLayout = (RelativeLayout)viewDialog;
// LayoutParams params = new LayoutParams(width, height);
// relativeLayout.setLayoutParams(params);
// Point point = new Point();
// Activity activity = getActivity();
// activity.getWindowManager().getDefaultDisplay().getSize(point);
// if(point.x > point.y)
if(width > height)
{
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
else
{
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
ViewParent parent = viewInput.getParent();
if(parent != null)
{
Log.d(TAG, "View already present. Removing.");
((ViewGroup)parent).removeView(viewInput);
}
LayoutParams params = new LayoutParams(width, height);
viewInput.setLayoutParams(params);
((ViewGroup)viewDialog).addView(viewInput, 0);
cancel = (Button)viewDialog.findViewById(R.id.btn_cancel);
focus = (Button)viewDialog.findViewById(R.id.btn_focus);
cancel.setOnClickListener(this);
focus.setOnClickListener(this);
setCancelable(false);
return viewDialog;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
Log.d(TAG, "onViewCreated of DialogFragment called.");
//getDialog().getWindow().setLayout(LayoutParams.MATCH_PARENT, height);
getDialog().getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
WindowManager.LayoutParams wmlp = getDialog().getWindow().getAttributes();
wmlp.gravity = Gravity.TOP | Gravity.LEFT;
wmlp.x = 10; //x position
wmlp.y = 450 * (id) + 10;
// wmlp.width = width;
// wmlp.height = height;
}
I am plotting a sine wave. The view has the correct size as the sine wave has a range of 0 to 12 but in the landscape orientation the displayed dialog box only gets a little more than half way, so 0 to 6 + is seen and then one has to wait for the wave to recycle as it plots from 6 to 12 before it becomes visible again when it goes back to 0. I AM able to place the dialog box upper left hand corner.
Does anyone know how to solve this problem? I went to the fragment because I was led to believe that the canned AlertDialog approach was fixed in width and there was nothing one could do. I am facing the same limitation with the DialogFragment.
try adding this code in on create() method after setContentView
getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
I gave up and created my graph in a ListView in a ViewFlipper. Not want I wanted but I got more real estate for the graph.
I have an activity whose layout I need to change after a rotation and part of the layout is a graph that is drawn using the width and height of the view that it will be placed into. The first time my code runs, the graph is drawn correctly, however after the rotation the width and height of the container view are not correct, in fact they appear to be the view as if it was not rotated.
Here is what I have so far,
In my manifest for the activity I am working:
android:configChanges="keyboardHidden|orientation|screenSize"
In my activity I have these following methods:
onCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
patient_id = extras.getInt("patient_id");
patient_name = extras.getString("patient_name");
historyDurationType = 12;
constructLayout();
}
constructLayout
public void constructLayout(){
if(landScape){
setContentView(R.layout.activity_bg_history_static_land);
//Set buttons
btnTwelve = (Button)findViewById(R.id.btnTwelveHoursLand);
btnTwentyFour = (Button)findViewById(R.id.btnTwentyFourHoursLand);
btnSeven= (Button)findViewById(R.id.btnSevenDaysLand);
btnTwelve.setOnClickListener(this);
btnTwentyFour.setOnClickListener(this);
btnSeven.setOnClickListener(this);
btnTwelve.setBackgroundColor(getResources().getColor(R.color.light_blue_regular));
btnTwentyFour.setBackgroundResource(android.R.drawable.btn_default);
btnSeven.setBackgroundResource(android.R.drawable.btn_default);
}else{
setContentView(R.layout.activity_bg_history_static);
//Set buttons
btnTwelve = (Button)findViewById(R.id.btnTwelveHours);
btnTwentyFour = (Button)findViewById(R.id.btnTwentyFourHours);
btnSeven= (Button)findViewById(R.id.btnSevenDays);
btnTwelve.setOnClickListener(this);
btnTwentyFour.setOnClickListener(this);
btnSeven.setOnClickListener(this);
btnTwelve.setBackgroundColor(getResources().getColor(R.color.light_blue_regular));
btnTwentyFour.setBackgroundResource(android.R.drawable.btn_default);
btnSeven.setBackgroundResource(android.R.drawable.btn_default);
btnComment = (Button)findViewById(R.id.btnCommentGraph);
btnComment.setOnClickListener(this);
populateOtherContent(officialReadings12);
TextView tvStats = (TextView)findViewById(R.id.txtStatistics);
Typeface chunkFiveFont = Typeface.createFromAsset(getAssets(), "fonts/chunkfivettfversion.ttf");
tvStats.setTypeface(chunkFiveFont);
TextView tvReading = (TextView)findViewById(R.id.txtReadingTitle);
tvReading.setTypeface(chunkFiveFont);
comment = null;
}
if(needData){
getLatestReadings();
}
populateGraph();
}
populateGraph
public void populateGraph(){
if(landScape){
graph_container = (LinearLayout)findViewById(R.id.graph_land_content_layout);
}else{
graph_container = (LinearLayout)findViewById(R.id.graph_content_layout);
}
//Create graphlayout
mainGraph_Layout = new RelativeLayout(this);
RelativeLayout.LayoutParams glParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mainGraph_Layout.setId(909);
mainGraph_Layout.setLayoutParams(glParams);
graph_container.addView(mainGraph_Layout);
graph_container.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if(needsGraph){
layoutGraph();
needsGraph = false;
}
}
});
}
layoutGraph
public void layoutGraph(){
viewWidth = mainGraph_Layout.getWidth();
viewHeight = mainGraph_Layout.getHeight();
//MORE STUFF IS HERE BUT NOT IMPORTANT
}
onConfigurationChanged
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
ActionBar actionBar = getActionBar();
if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){
//Config is landscape here
actionBar.hide();
needData = false;
landScape = true;
needsGraph = true;
constructLayout();
}else{
//Config is portrait here
actionBar.show();
needData = false;
landScape = false;
needsGraph = true;
constructLayout();
}
}
After rotation, it is at the layoutGraph() viewWidth and viewHeight objects where I have the problem. I had assumed by that point (having used the global layout listener) that the values would be correct. My understanding was that the listener would only have been triggered once "graph_container" was completed (and landscape or portrait) and so when calling layoutGraph() the width and height of "mainGraph_layout" (a child a graph_container, widths and heights set to MATCH_PARENT) would be good to go. It appears that the width and height I am getting are as if the phone is still portrait, and worth noting it appears that the removal of the action bar has also been taken into account.
Sorry for the long question but I thought it best to show all the code. If anything else needs to be shown then please let me know.
Thanks in advance,
Josh
There is a much better way to do this.
Use resource folders
Put your default layout files in res/layout, and the ones for landscape in res/layout-land. In other words, move res/layout/activity_bg_history_static_land.xml to res/layout-land/activity_bg_history_static.xml.
In onCreate, call
setContentView(R.layout.activity_bg_history_static);
The system will pick the file from res/layout-land when you are in landscape orientation, res/layout otherwise.
If you have views that are only present in one layout but not the other e.g. the comment button, wrap the code inside a null check like this:
btnComment = (Button) findViewById(R.id.btnCommentGraph);
if (btnComment != null) {
btnComment.setOnClickListener(this);
}
For populateGraph(), make sure both res/layout/activity_bg_history_static.xml and res/layout-land/activity_bg_history_static.xml has android:id="#+id/R.id.graph_content. Then you can do findViewById(R.id.graph_content) and get the LinearLayout you need.
Save data across rotation
In your activity, override onSaveInstanceState(), and save the data from getLatestReadings() into the bundle.
Then, in onCreate:
if (savedInstanceState == null) {
getLatestReadings();
} else {
// Restore latest readings from savedInstanceState
}
With that, you can let the system handle the rotation i.e. remove this from your manifest:
android:configChanges="keyboardHidden|orientation|screenSize"
Since the system is handling the rotation, you don't need to have a view tree observer any more. And you don't have to override onConfigurationChanged.
I'm trying to make a app that allows you to drag shapes around. It works fine on smart phones, but not on my Acer a500 tablet
When I get the height by calling
ih=getWindowManager().getDefaultDisplay().getHeight()-25;
I get a value thats only 1/3 of what it should be, thus I can only drag the sahpes 1/3 the way down. If the tablet is horizonatl it goes 1/2 way down.
Why is this methed returning the wrong values for the height on my tablet??
public class cPlay extends cBase implements OnClickListener {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.play);
int w=getWindowManager().getDefaultDisplay().getWidth()-25;
int h=getWindowManager().getDefaultDisplay().getHeight()-25;
BallView ballView=new BallView(this,w,h);
setContentView(ballView);
} // end function
public void onClick(View v) {
finish();
} // end function
} // end class
Try this:
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int Width = displaymetrics.widthPixels;
Methods getWidth() and getHeight() are deprecated in Display.
Try to use DisplayMetrics.
Also you might want to get the size of your view's container by calling getMeasuredWidth() and getMeasuredHeight() after onMeasure() was called to get more precise size of your view.
I'm wondering how to measure the dimensions of a view. In my case it is aan Absolute Layout. I've read the answers concerning those questions but I still don't get it.
This is my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
AbsoluteLayout layoutbase = (AbsoluteLayout) findViewById(R.id.layoutbase);
drawOval();
}
public void drawOval(){ //, int screenWidth, int screenHeight){
AbsoluteLayout layoutbase = (AbsoluteLayout) findViewById(R.id.layoutbase);
int screenWidth = layoutbase.getWidth();
int screenHeight = layoutbase.getHeight();
Log.i("MyActivity", "screenWidth: " + screenWidth + ", screenHeight: " +screenHeight);
Coordinates c = new Coordinates(BUTTONSIZE,screenWidth,screenHeight);
...some code ...
((ViewGroup) layoutbase ).addView(mybutton, new AbsoluteLayout.LayoutParams(BUTTONSIZE, BUTTONSIZE, c.mX, c.mY));
mybutton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
showText(mybutton);
}
});
}
public void showText(View button){
int x = findViewById(LAYOUT).getWidth();
int y = findViewById(LAYOUT).getHeight();
Toast message = Toast.makeText(this, "x: " + x , Toast.LENGTH_SHORT);
message.show();
}
The getWidth() command works great in showText() but it does not in drawOval(). I know it looks a bit different there but I also used the int x = findViewById(LAYOUT).getWidth(); version in drawOval(), and x/y are always 0. I don't really understand why there seems to be no width/height at that earlier point. Even if I actually draw a Button on the Absolute Layout, getWidth() returns 0. Oviously I want to measure the sizes in drawOval().
I think will help you.
LinearLayout headerLayout = (LinearLayout)findviewbyid(R.id.headerLayout);
ViewTreeObserver observer = headerLayout .getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
int headerLayoutHeight= headerLayout.getHeight();
int headerLayoutWidth = headerLayout.getWidth();
headerLayout .getViewTreeObserver().removeGlobalOnLayoutListener(
this);
}
});
}
getWidth() is giving you 0 because onCreate is called before layout actually happens. Due to views being able to have dynamic positions and sizes based on attributes or other elements (fill_parent for example) there's not a fixed size for any given view or layout. At runtime there is a point in time (actually it can happen repeatedly depending on many factors) where everything is actually measured and laid out. If you really need the height and width, you'll have to get them later as you've discovered.
This specially deal with Dimensions so
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
This may help you in managing dimensions.
Note: This returns the display dimensions in pixels - as expected. But the getWidth() and getHeight() methods are deprecated. Instead you can use:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
as also Martin Koubek suggested.
If your goal is to simply draw an oval on the screen, then consider creating your own custom View rather than messing around with AbsoluteLayout. Your custom View must override onDraw(android.graphics.Canvas), which will be called when the view should render its content.
Here is some extremely simple sample code that might help get you started:
public class MainActivity extends Activity {
private final Paint mPaint = new Paint();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
// create a nested custom view class that can draw an oval. if the
// "SampleView" is not specific to the Activity, put the class in
// a new file called "SampleView.java" and make the class public
// and non-static so that other Activities can use it.
private static class SampleView extends View {
public SampleView(Context context) {
super(context);
setFocusable(true);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.CYAN);
// smoothen edges
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(4.5f);
// set alpha value (opacity)
mPaint.setAlpha(0x80);
// draw oval on canvas
canvas.drawOval(new RectF(50, 50, 20, 40), mPaint);
}
}
}
This give you screen resolution:
WindowManager wm = (WindowManager)context.getSystemService(context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point outSize = new Point();
display.getSize(outSize);
kabuko's answer is correct, but could be a little more clear, so let me clarify.
getWidth() and getHeight() are (correctly) giving you 0 because they have not been drawn in the layout when you call them. try calling the two methods on the button after addView() (after the view has been drawn and is present in the layout) and see if that gives you the expected result.
See this post for more information.