Make content inside scrollView match display size - android

I have a ScrollView with a RelativeLayout inside it.
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true">
<RelativeLayout
android:id="#+id/toWrap"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/background_color">
I want to make this RelativeLayout not fill its parent, but fill the display.
I want that because when I open the keyboard, the layout gets ugly.
I've tried to create a ExpandableRelativeLayout subclass with onDraw like this:
#Override
protected void onDraw(Canvas canvas)
{
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, (int)(metrics.heightPixels * metrics.density)));
super.onDraw(canvas);
}
But I constantly received this error:
E/AndroidRuntime(15331): java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.FrameLayout$LayoutParams`
How do I do that?
Thanks.

I think you should use RelativeLayout.LayoutParams instead of layoutparams. That what I always do and didnot have any errors. Also if you are using ecllipse and you altered the xml and this error occured after that then you should close ecllipse and start again. This is a bug in ecllipse where at some point your R.java stops generating and classcastexception occurs.

Related

Inflate a custom view from XML, then set her height and witdh programmatically

I'm loosing myself in an custom size View problem since a couple of days. After some long research, I finally decide to ask your help... please ! T_T
In my app, I created a custom View with the XML calendrieradmin_day.xml :
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/CalendrierAdmin_Day_Event_TableRow"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<!-- <TextView
android:id="#+id/CalendrierAdmin_Day_Event_TextView_Name"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:gravity="center" />-->
</TableRow>
For now, it is a simple TableRow, but I'll need to add some other things in the future. (The commented TextView, for example).
I made three classes for using it : Row, EventRow and EmptyRow. Row is abstract and EventRow and EmptyRow inherit of Row. Also, Row inherit of TableRow.
I want to add several EventRow and EmptyRow in a TableLayout and I need to resize them dynamically.
In the constructor method of EmptyRow and EventRow, I call an init() method. Here the one of EventRow :
private void init(Context c, TableLayout root) {
root = (TableLayout)LayoutInflater.from(c).inflate(R.layout.calendrieradmin_day_event, root, true);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) root.getLayoutParams();
lp.height = getHeightOfMinute() * getDuree();
lp.width = getTheWidth();
/*
Some other stuff
...
...
*/
this.setLayoutParams(lp);
root.addView(this);
setOnClickListener(this);
setOnLongClickListener(this);
}
Of course, it doesn't work as excepted. The EventRow is not showed.
root is my TableLayout I pass in the constructor. getHeightOfMinute() and getDuree() work correctly and give me the right sizes. I used to use the inflate() method like inflate(R.layout.calendrieradmin_day_event, null, false) and it worked fine, but Eclipse gave me a warning, telling me I shouldn't pass null as the RootView argument. Although everything worked fine, I begun to search another solution and this is where I gone so far...
I used the setMinimumHeight() and setMinimumWidth() method to rezise my EventRow and EmptyRow. It works, but I think there is a better way to do that. I tried A LOT of solutions but I messed up ! I think there is something I still not catched about the functioning of inflate() and/or LayoutParams.
Could you help me ? Thanks in advance !
Please tell me if you need more piece of Source code.
PS: Sorry for the bad english, I'm french.
I finally managed it, but a lot of things have been changed.
First, I drop the TableLayout and TableRow. Now it is simply some LinearLayout.
calendrieradmin_day.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/CalendrierAdmin_Day_Event_LinearLayout_Container"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:orientation="horizontal" >
<TextView
android:id="#+id/CalendrierAdmin_Day_Event_TextView_Name"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="left"
android:background="#drawable/background_event_full"
android:gravity="left" />
</LinearLayout>
And this is the init() method :
private void init(Context c, LinearLayout root) {
LinearLayout container = (LinearLayout) LayoutInflater.from(c).inflate(R.layout.calendrieradmin_day_event, root, false);
TextView name = (TextView) container.findViewById(R.id.CalendrierAdmin_Day_Event_TextView_Name);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0, duree);
container.setLayoutParams(lp);
name.setLayoutParams(lptv);
name.setText(e.getNom());
root.addView(container);
name.setOnClickListener(this);
name.setOnLongClickListener(this);
}
Pay attention to the LayoutParams lp (It's a LinearLayout.LayoutParams). duree is the duration of my event, in minutes.
My EventRow are intended to be in an another LinearLayout, llEvents. It contains all the events for one day, so 1440 minutes (60 x 24). As a result, the weightSum of llEvents is 1440.
I dropped the EmptyRow and the Row class to. I just add some empty LinearLayout to llEvents for the free time schedules, with there duration as weight.
It's REALLY important to presize a "0" height in the LayoutParams
Hope It will help someone ;-) !

Android: How to apply LayoutParams to my RelativeLayout

I'm having difficult with this bit of code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
RelativeLayout layout = (RelativeLayout)findViewById(R.id.RelativeLayout1);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
I have my RelativeLayout1 in xml like this:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ScrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingLeft="60dp"
android:paddingTop="53dp" >
But when I apply the scrollview, the fill_parent for RelativeLayout1 does not work as it should when it is not a child of scrollview. When it is not a child (i.e. I remove scrollview completely) then the relative layout covers the whole screen as I like it to. But when I put it inside scrollview, it only reaches the last element (a button) inside the relativelayout even though I use fill_parent.
So I am trying it programmatically to see if it makes a difference, but I can't seem to figure out how to apply my params variable to my layout one in the first bit of code. If you have any other ideas, do let me know as well.
You have forgotten to call the setter method layout.setLayoutParams(params).
To apply your created parameters you have to give them to the actual layout.
Be cautious with using fill_parent when the parent is a ScrollView. As the Scroll view adapts its size to its children.
I figured out how to solve my problem by adding a field to the scrollview and not doing this programmatically. In the ScrollView, I had to set the following:
android:fillViewport="true"
Add the attribute android:fillViewport="true" to your ScrollView if you want the RelativeLayout to fill up the ScrollView.
See Romain Guy's post about the same here: ScrollView's handy trick

fake a View to portrait inside landscape-mode

I have an Activity in Landscape-Mode. Inside there is a Custom-Title-View aligned like this:
Is it possible to keep the landscape mode and 'fake' this one View into portrait-mode like this:
I have tried to overwrite my custom TitleView and put something like this to draw(Canvas)
public class VerticalTitle extends Title{
public draw(Canvas){
canvas.save();
canvas.rotate(getWidth() / 2, getHeight() / 2);
// i tryed many translations, but get none to work
canvas.translate(0, getHeight());
super.draw(canvas);
canvas.restore()
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
}
If it is on any interest, The TitleBar extends from RelativeLayout and has fixed height and fill_parent width
The setRotate parameter from View is not an option, because the app should stay compatible to 2.2.
you have to extend Text view And build your custom vertical TextView first see these two links for more details
Vertical TextView
Vertical rotated label
and after that in your Layout-land you can use this Xml file for your layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.yourpackage.CustomVerticalTextView
android:layout_width="42dp"
android:layout_height="fill_parent"
android:text="#string/hello"
android:background="#0000FF" />
</LinearLayout>
If you want to rotate the layout instead of rotating all of its children by 90 degrees use
LayoutAnimationController
see this SO thread for more details
I have never done this but I found two other answers here on SO that show ways you might accomplish this.
The first one involves extending the TextView class, and is here. Since you want to do a whole view though, I think the next answer is better suited to your situation.
The other answer is to create an animation using rotation to deal with it. That answer is here.

Android get Fragment width

I have a layout with 3 fragments:
<LinearLayout android:id="#+id/acciones"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/fragment1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
</LinearLayout>
<LinearLayout
android:id="#+id/fragment2"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:id="#+id/f3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
</LinearLayout>
</LinearLayout>
In the first fragment I have a TableLayout in which I have one custom TextView in each row.
I want to know the width of the fragment because if the custom TextView is wider than the fragment, I'll set the number of lines necessary.
This is what I've done in my custom TextView:
#Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mMaxWidth = (float) (getMeasuredWidth());
}
With this line I got the width from the three Fragments, not only the one which contains the custom TextView.
Thanks.
You should be able to set the width of the TextView to be fill_parent, in which case it will do the wrapping for you. You should not set the widths of your layouts to be match_parent since it is inefficient when you're using layout weights.
Since android's layout system is occasionally mysterious with regards to view sizes, if setting the TextView width to be fill_parent actually makes it take up the whole screen (as your question appears to be implying) do the following:
Set your TextView width to 0 by default. In onCreate of your activity, after setting the content view:
findViewById(R.id.acciones).getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
final int fragmentWidth = findViewById(R.id.releventFragmentId).getWidth();
if (fragmentWidth != 0){
findViewById(R.id.yourTextViewId).getLayoutParams().width = fragmentWidth;
}
}
});
By setting the TextView's width to 0 initially, you prevent it from changing the widths of the fragments. Then you can use a view tree observer to get the width of whatever fragment you're interested in (by looking at its root view) after layout has occurred. Finally you can set your TextView to be that exact width, which in turn will do the wrapping for you automatically.
Note that onGlobalLayout can be called multiple times and is regularly called before all of the views have been completely laid out, hence the != 0 check. You will also probably want to do some kind of check to make sure that you only set the width of the text view once, or otherwise you can get into an infinite layout loop (not the end of the world, but not good for performance).

Android - canvas onDraw does not fire

I am trying to add a canvas view to a relative layout inside a horizontal scroll view.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#fff"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/hsv"
android:layout_width="fill_parent"
android:background="#EEDB00"
android:layout_height="30mm">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/canvas"
android:background="#000"
android:layout_width="300mm"
android:layout_height="20mm">
</RelativeLayout>
</HorizontalScrollView>
</RelativeLayout>
I created a class called CanvasView which extends View, and I drew some basic shapes by over-riding onDraw(). However the canvas does not appear in the relativelayout, when I do:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
cView = new CanvasView(this);
rLayout = (RelativeLayout)this.findViewById(R.id.canvas);
rLayout.addView(cView);
}
However, when I directly add it by calling setContentView(cView); it works. On digging, I found that when I call addView(), the onDraw() is not firing at all, and hence the canvas is not drawn... Any ideas on how to fix this?
I'm not in a position to test this myself at the moment, but I think your problem is that you're not applying any LayoutParams to the View, which may mean it occupies no screen space. If a View is ever off-screen or completely obscured or the system otherwise decides that nothing it draws will be visible, then I believe onDraw() won't be called at all.
Try setting some width and height to your View when you add it to your RelativeLayout:
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(50,50);
rLayout.addView(cView, params);

Categories

Resources