I have 4 Relative layouts : ( as you can see in the animation)
The green RelativeView
The "type something & icons" RelativeView
The gray speperator RelativeView
The bottom Textview
Each RelativeView is "below" it's previous relative view.
By design , when the 2 inner views are closed , the button should be half top above the green , and half bottom above the text ( just like the animation shows)
Ok , So I added a button which is found inside the "bottom textview"
But in order for the bottom to be only half bottom above the view , I added it a negative Margin :
So here it is without the negative margin :
And here it is with the negative margin ( the desired result)
So when I clicked the button I simply hide/show ( + animation with android:animateLayoutChanges="true") the inner 2 middle views
So where is the problem ?
Question
I don't know why but only the bottom half of the button is clickable ! I guess it is because that half is inside its container view while the top half is not in its view...( maybe i'm wrong)
But if I remove the negative margin and the button is fully in its container - then the button is 100% fully clickeable ( both top half and bottom half)
As you can see in the animation (last frames) - when i click the top half - nothing happens....
How can I fix that ?
Maybe i've taken a wrong initial approach ?
nb : some more visualization of structure :
Have your button as a sibling to the RelativeLayouts rather than as a child. This works as you want it to.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">![enter image description here][1]
<RelativeLayout
android:id="#+id/red"
android:background="#android:color/holo_red_dark"
android:layout_width="match_parent"
android:layout_height="100dp">
</RelativeLayout>
<RelativeLayout
android:id="#+id/green"
android:layout_below="#id/red"
android:background="#android:color/holo_green_dark"
android:layout_width="match_parent"
android:layout_height="100dp">
</RelativeLayout>
<RelativeLayout
android:id="#+id/blue"
android:background="#android:color/holo_blue_dark"
android:layout_below="#id/green"
android:layout_width="match_parent"
android:layout_height="100dp">
</RelativeLayout>
<Button
android:id="#+id/button"
android:layout_centerHorizontal="true"
android:layout_below="#id/green"
android:layout_width="wrap_content"
android:text="Hide Green"
android:layout_marginTop="-24dp"
android:layout_height="wrap_content"/>
</RelativeLayout>
Looks like this and the button moves up/down as setVisibility is toggled between GONE/VISIBLE for green RelativeLayout
Your button belongs to bottom RL. When android routes ACTION_DOWN it checks layout's borders and gives events to viewgrops (VG) which have event coordinates inside. Then VG proporate event to it's children based on it's coordinates.
So when you click on upper part of your button touch event given to grey RL and button which belonges to blue RL doesn't get it. Actually event given to Window -> Root ViewGroup -> Some Other ViewGroup -> View. And routing happens base on coordinates. It is true for ACTION_DOWN which starts touch, but not all MotionEvent processed this way.
As a solution, you can move button to another groupview which can route touch event properly. Or maybe try to use touch delegates.
Related
I appreciate the title is not very well written but its a little difficult to explain my issue succinctly...
I'm creating an Android app and I've got a custom chart view that has a little popup that should be able go outside the bounds of the chart view itself and will position itself based on where you select on the line chart.
I'm having trouble getting this to work when I have more than 1 parent view group in the hierarchy. This is my layout xml:
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false">
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.myapp.ui.views.chart.line.LineChartView
android:id="#+id/lineChartView"
android:layout_width="match_parent"
android:layout_height="228dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
if I remove the CardView so there is just the ConstraintLayout as the parent, it works. If I make the CardView bigger in the Y direction it allows enough space to draw the popup on the extra card space. But as it like this, it doesnt work.
It's kind of like it only allows you to draw up the hierarchy once onto the parent but not again onto the grandparent view.
How do I allow it to draw over the top of any and all parent views so its like a true "popup"?
Hope that makes sense
Simple answer: You can't draw outside the view's bounds.
<RelativeLayout>
<RelativeLayout
android:width="400dp"
android:height="400dp">
<LineChartView
android:width="100dp"
android:height="100dp"/>
<RelativeLayout>
</RelativeLayout>
In the above case, if you check the Canvas size in LineChartView's onDraw(canvas), you will find the height and width are 100dp. And that is the size of your View. So you can draw only within that space. The parent of your View doesn't really have any impact, unless you set your View's width/height as a dynamic value like MatchParent or WrapContent. If you do MatchParent on your View, then the width/height of the Canvas becomes 400dp.
In essence, the size of the Canvas determines what space is available to draw and what is visible on screen. To solve your use case, you could make you LineChartView fill the entire screen. But with this approach, you will have to keep track of where to draw the actual graph. If the screen is scrollable, then it will add more complexity.
The other approach, which I think is the easy one, is to have two views (One for the LineChart, and the other for the PopUp). The LineChartView will draw the actual graph, and the PopUp view will cover the entire screen. When the user selects something in the graph, you just need to pass the Graph's values along with the Absolute position on where to draw the popUp to the PopUpView. This way you can draw the popUp anywhere on the screen.
I have a TextView and a Button in an android XML layout(TextView is at left most side and Button is at right most side in the same line), as the text in TextView is dynamic so it should take a minimum width for some initial text to be visible. As width of devices changes the minimum width of TextView does not look good all the time.
For example if width of device becomes greater, then the minimum width alloted to the TextView would look so bad because it would not use more space available on the screen.
So what I want to do is to set the minimum width of TextView according to the position of Button present at the Right most side of the screen
Like minWidth = "leave this dp" form Button.
I hope you have understood it well if not then ask me more about it.
Seeking for attributes to use.
Use a LinearLayout with horizontal orientation put that TextView and Button inside that LinearLayout. Give weight of that TextView to 1 and set width to 0dp and use wrap_content for Buttn's width
Code snippet
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"/>
</LinearLayout>
Put button and textview inside linearlayout and set weight for textview and button according your requirement. it will set layout view according device screen size.
I am trying to find a way to darken the entire screen except for a specific gridview item (in order to draw attention to this specific item).
I have been able to darken the whole screen by putting a black partially transperant view in front of the app content like this:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<GridView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/gridView"
android:numColumns="2"/>
<View
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#88000000" />
</FrameLayout>
Unfortunately I cannot come up with a way to make one gridview item not get darker. Can anyone help me out here?
Inflate the gridview position view in a custom dialog which maintains its x, y position on screen and 'darkens' the rest of the layout.
Could this also work? Set a background color to whatever you want and in getView return transparent image to all grid items except the one you want to display.
how do I get a TextView into the visible area of a screen by scrolling a ScrollView, if the TextView is not a direct child of the ScrollView?
I've got a LinearLayout view that has a TextView at the top, then a ScrollView and below a Button:
<LinearLayout
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_height="wrap_content"/>
<ScrollView
android:id="#+id/s"
android:layout_height="0dip"
android:layout_weight="1" >
<TableLayout
android:id="#+id/t"
android:layout_height="wrap_content" >
<TableRow
android:id="#+id/r" >
<TextView
android:id="#+id/a"/>
<TextView
android:id="#+id/b"/>
<TextView
android:id="#+id/c"/>
</TableRow>
</TableLayout>
</ScrollView>
<Button
android:layout_height="wrap_content"/>
</LinearLayout>
That generated a wholly filled screen with the label at the top border, the button at the bottom border, and a table between it; depending on how many rows this table has, you can scroll it or not.
The contents of the table are generated by Java code, I just added one row as example of what is inserted there.
I now need to make sure a certain row (not necessarily the last one) is visible by scrolling vertically. I can access every element from s to c, but I can't figure out the code to make the ScrollView s scroll at all.
I tried requestChildRectangleOnScreen, scrollBy and, scrollTo, but possibly always with the wrong arguments.
For now I don't care whether TextView a is vertically centered or at the bottom or top border, it would indeed be great if it was visible at all. X-scroll should stay 0, ideally (i. e. leftmost position).
In case this is important: this function is only called when the user enters the screen with a special Intent that's telling the screen to scroll to TableRow x (it's just to show the latest change).
If you need even more information, please ask.
Thank you!
The problem was indeed that I called the function directly from a sub call of onCreate. This meant the layout wasn't done yet, thus all scrolling was done before the elements had a height and so it scrolled by 0 pixels.
The solution is to use View.post(Runnable r):
ScrollView s = (ScrollView) findViewById(R.id.s);
TextView a = (TextView) findViewById(R.id.a);
s.post(new Runnable() {
public void run() {
int[] location = new int[2];
a.getLocationInWindow(location);
int y = location[1];
s.getLocationInWindow(location);
s.scrollTo(0, y-location[1]); // or some other calculation
}
});
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="vertical">
<ScrollView android:id="#+id/scroll"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:fillViewport="true">
<adam.music.testfont.NwcDrawingArea android:id="#+id/NwcDrawingArea"
android:layout_height="2000dp"
android:layout_width="2000dp"
/>
</ScrollView>
</LinearLayout>
I created Android Project and edited main.xml as above.
And then I customized view to draw image.
To see the effect of scrolling customized view I set width and height as above.
Now I can see the image in a customized view but it doesn't scroll.
Could you help me what the problem is?
Should I add something more?
There's an interplay between ScrollView and its contents. For example, if, instead of your NwcDrawingArea widget, you inserted this TextView into your ScrollView:
<TextView android:text="8This is a lot of text 7This is a lot of text 6This is a lot of text 5This is a lot of text 4This is a lot of text 3This is a lot of text 2This is a lot of text 1This is a lot of text"
android:layout_width="10dp"
android:layout_height="2000dp"
android:background="#FF00FF00"
/>
You'll see a skinny green vertical TextView whose text is longer than the screen, and the ScrollView shows scrollbars that let you see the hidden part of the TextView to the extent of the text. Now, change the TextView layout_width="2000dp". The TextView becomes a full-screen green area that has a single line of text that runs off the right side of the screen. ScrollView, of course, shows no horizontal scroll bars. However, ScrollView shows no vertical scroll bars either, even though we sized the TextView to be much longer than the screen. ScrollView is attempting to determine the visually interesting portion of its contents, so you need to understand the behavior for whatever widget you are subclassing.
For example, ScrollView respects the layout sizes of LinearLayout and RelativeLayout in the way that you expected it to behave with TextView. In fact, it is common to make a LinearLayout or RelativeLayout -- rather than a view such as TextView -- the child of a ScrollView. Drop your TextView in a fixed-height LinearLayout and you should get the behavior that you expected.