I am trying to create the effect seen on this webpage for example
http://www.soyuzcoffee.com/ru/home
the part where as you scroll it appears as the main content is scrolling over the big images (images that act as dividers between sections)
I am very close but if the image is smaller that the height of the view (image does not fill the entire screen) the image scrolls up like it normally would until it hits the top. I am trying to make it look like the image is stationary and the frame is moving over it.
here is my layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.pinnedscrollview.CustomScrollView
android:id="#+id/scroller"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.pinnedscrollview.PinnedImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.pinnedscrollview.PinnedImageView
android:id="#+id/image2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.pinnedscrollview.PinnedImageView
android:id="#+id/image3"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.pinnedscrollview.PinnedImageView
android:id="#+id/image4"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</LinearLayout>
</com.example.pinnedscrollview.CustomScrollView>
</RelativeLayout>
Then I have an onScrollChangedListener that runs this method everytime the scroll position changes
private void handleScroll(ViewGroup source, int top) {
ViewGroup container = (ViewGroup) source.findViewById(R.id.container);
final int count = container.getChildCount();
for (int i = 0; i < count; i++) {
View item = container.getChildAt(i);
View v = null;
if(i == 0){
v = item.findViewById(R.id.image);
}else if(i == 1){
v = item.findViewById(R.id.image2);
}else if(i == 2){
v = item.findViewById(R.id.image3);
}else if(i == 3){
v = item.findViewById(R.id.image4);
}
source.getHitRect(mTempRect);
if (v != null && v.getLocalVisibleRect(mTempRect)) {
((PinnedImageView) v).reveal(source, item.getBottom(),item.getTop());
}
}
}
Then this is the reveal method that just sets the Translation in the Y direction
public void reveal(View scroller,int parentBottom,int parentTop) {
float previousOffset = mOffsetY;
if(parentTop - scroller.getScrollY() < 0){
mOffsetY= Math.abs(parentTop - scroller.getScrollY());
}else{
mOffsetY = Math.min(0, scroller.getHeight() - (parentBottom - scroller.getScrollY()));
}
if (previousOffset != mOffsetY) {
setTranslationY(mOffsetY);
}
}
I am not sure if I need to do something with the Matrix of the image in the onDraw and redraw the bitmap or not.
Any ideas or other ways that I can accomplish something similar to that website?
I would set the desired image as a background image of a containing layout. Then set appropriate transparencies and place the scrollable view as a child of the parent layout that contains the image. You may even be able to set the background of the scrollable view itself.
You then may be able to use conditionals etc to adjust the frame of the background image and swap images based on the scroll position.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_marginTop="48dp"
android:background="#drawable/tmf_background"
>
<ImageView
android:src="#drawable/the_lineup_header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="16.5dp"
android:contentDescription="#string/noDescription" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/tmf_sub_header" >
<TextView... />
<Button ... />
<Button... />
<Button ... />
<TextView ... />
</LinearLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#drawable/tmf_divider"
android:background="#android:color/transparent" >
</ListView>
</LinearLayout>
Here is a chunk of the xml for the free app I did for True Music Festival for it's first year.
https://play.google.com/store/apps/details?id=com.fyresite.truemusicapp
There we have a single background image that stays static while the content scrolls over it. Combining that with your scroll position listener you should be able to, at the very least, change the background image as you scroll. You could then try transforming the background image to get that scrolling effect on the site.
You may find this question to be useful Android: Moving background image while navigating through Views
Related
I have a slight problem getting my layout_weight to work. I am creating a custom bottomBar. But i cant make it to stretch as i want it to.
Bottom Bar View
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/bottom_bar_root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/bottom_bar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="4"
android:orientation="horizontal"/>
</RelativeLayout>
This is the big container i am adding my buttons (items) to.
Bottom Bar Item
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<android.support.v7.widget.AppCompatImageView
android:id="#+id/bottom_bar_item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/arrow_up_float"/>
<TextView
android:id="#+id/bottom_bar_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEXT"/>
</LinearLayout>
This is my items that i add dynamically to the view. But somehow the view is not stretched properly.
But when i hardcode it in. It works. So could it be that layout weight does not work dynamically?
How i add the views (items)
private void updateItems(final List<BottomBarTab> bottomBarTabs) {
if (bottomBarTabs.size() < TABS_COUNT) {
throw new RuntimeException("Not enough buttons for bottomBar");
}
for (int i = 0; i < TABS_COUNT; i++) {
bottomBarTabs.get(i).setOnClickListener(this);
bottomBarTabs.get(i).prepareLayout();
container.addView(bottomBarTabs.get(i));
}
}
Screenshot
LayoutWeight is given to inner components of layout only not on parent Linearlayout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:weightSum="2">
<android.support.v7.widget.AppCompatImageView
android:id="#+id/bottom_bar_item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="#android:drawable/arrow_up_float"/>
<TextView
android:id="#+id/bottom_bar_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TEXT"/>
</LinearLayout>
public void prepareLayout() {
View view = inflate(getContext(), R.layout.bottom_bar_item,this);
LinearLayout.LayoutParams params =
new LayoutParams(0,LayoutParams.MATCH_PARENT,LAYOUT_WEIGHT);
view.setLayoutParams(params);
if(backgroundColor != null) {
view.setBackgroundColor(backgroundColor);
}
TextView titleText = (TextView) view.findViewById(R.id.bottom_bar_item_text);
titleText.setText(title);
AppCompatImageView imageView = (AppCompatImageView) view.findViewById(R.id.bottom_bar_item_icon);
imageView.setImageResource(iconResId);
}
I changed in my prepareLayout function and put new layoutParams. Because somehow after inflation. The view ignores the weight that was set to it. So i had to force it by code. Maybe this is a android bug?
I have a list(container) with couple views I'd like to hide and show again when collapse/expand button is clicked.
No problem so far, now i want to animate hiding and showing of my nested views, i didn't want to complicate with animations and i went with default ones.
That is why i added android:animateLayoutChanges="true" to container layout, this works great when showing/expanding views, but looks terrible when hiding/collapsing views.
Is there any particular reason behind this behavior?
Code and example below:
Code
container layout
<LinearLayout
android:id="#+id/izdelek_podrponud_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:animateLayoutChanges="true"
>
</LinearLayout>
child view layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/spacing_medium"
android:paddingBottom="#dimen/spacing_medium"
android:gravity="center_vertical">
<View
android:layout_width="5dp"
android:layout_height="5dp"
android:background="#color/colorPrimary"/>
<TextView
android:id="#+id/row_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/spacing_small"
android:textSize="#dimen/font_size_60px"
android:textColor="#color/black"/>
</LinearLayout>
And this is how i handle showing and hiding;
private void showViews(LinearLayout container, int visible, boolean show) {
if (container.getChildCount() > visible) {
for (int i = visible; i < container.getChildCount(); i++) {
if (show) {
container.getChildAt(i).setVisibility(View.VISIBLE);
} else {
container.getChildAt(i).setVisibility(View.GONE);
}
}
}
}
I've been trying to measure the pixel dimensions of a view within a RelativeLayout that's within another RelativeLayout:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="60"
>
...
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/labels_placeholder"
android:id="#+id/player_section_layout"
>
<LinearLayout
android:id="#+id/player_section_background"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
android:weightSum="100">
<!--The view above is what I'm trying to measure-->
<LinearLayout
android:id="#+id/player_section_background_left"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="50"
android:background="#AAAAAA"
android:orientation="horizontal" />
<LinearLayout
android:id="#+id/player_section_background_right"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="50"
android:background="#DD0000"
android:orientation="horizontal" />
</LinearLayout>
<HorizontalScrollView
android:id="#+id/player_section"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_alignTop="#id/player_section_background">
<ImageView
android:id="#+id/waveform_placeholder"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:scaleType="centerInside"
/>
</HorizontalScrollView>
</RelativeLayout>
</RelativeLayout>
I tried calling getMeasuredHeight() and getMeasuredWidth() right after referring to it in onCreateView() of the fragment:
waveformBackground = (LinearLayout)result.findViewById(R.id.player_section_background);
waveformBackground.post(new Runnable() {
#Override
public void run() {
Log.i("bckg_layout_dims", waveformBackground.getMeasuredWidth()+" "+waveformBackground.getMeasuredHeight());
}
});
And it returns 0 for both.
I did hear something about it not working before the view is being drawn, but I don't know when exactly it finishes drawing. Is it after OnCreateView, and if so, can I call it in OnActivityResult?
The problem you are facing is because the view is being drawn after you ask for the height and width. I used a ViewTreeObserver which constantly listens for changes in the views, and can access the measurements after the views has been drawn. Im not sure this is the best solution for your problem but you should look into it. Here's an example:
mTitleContainer.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int toolBarHeight = mTitle.getHeight() + mSubtitle.getHeight() + (int) TOOLBARPADDING;
if (toolBarHeight != mLastTitleHeight) {
CollapsingToolbarLayout.LayoutParams layoutParams = (CollapsingToolbarLayout.LayoutParams) mTitleToolbar.getLayoutParams();
layoutParams.height = toolBarHeight;
mTitleToolbar.setLayoutParams(layoutParams);
mLastTitleHeight = toolBarHeight;
}
}
}
);
I have to define 5 layouts on the screen and place them like a 3x3 grid. Layouts is empty.
At some moment I want programmatically to add some view on one layout and that view mustn't grows over allocated size of layout. In other words I want to have layout in which to put any view and it will be guaranty that it won't grows over that layout. Important note: I don't have rights to change manually size of added view, I only can to control its maximum size.
I have right now such layout:
<RelativeLayout
android:id="#+id/pluginsLayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/mainButtons"
android:layout_below="#+id/paramsLayout">
<RelativeLayout
android:id="#+id/capturingPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="fill_horizontal|left"
android:layout_above="#+id/processingPluginLayout">
</RelativeLayout>
<RelativeLayout
android:id="#+id/processingPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="fill_horizontal|left"
android:layout_above="#+id/filterPluginLayout">
</RelativeLayout>
<RelativeLayout
android:id="#+id/filterPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="fill_horizontal|left|bottom"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true">
</RelativeLayout>
<RelativeLayout
android:id="#+id/exportPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="fill_horizontal|right"
android:layout_above="#+id/viewfinderPluginLayout">
</RelativeLayout>
<RelativeLayout
android:id="#+id/viewfinderPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="fill_horizontal|bottom|right"
android:layout_toLeftOf="#+id/filterPluginLayout"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true">
</RelativeLayout>
</RelativeLayout>
And I added new view in code:
public void addVFPluginView(View view)
{
((RelativeLayout)MainScreen.thiz.findViewById(R.id.viewfinderPluginLayout)).addView(view);
}
I expect to got like this behaviour:
But I got only this, view fill entire parent layout:
Note: I use API8 (don't have GridLayout)
u can use grid layout in API8.
I've managed to solve this issue.
The main idea was to control view's sizes by myself programmatically.
I calculate appropriate proportion for each zone and when somebody add a new view to some of this layout I check suitability of the size of this view to the allocated size of layout. If size is not suitable I modify LayoutParams for this View.
Here is the xml of empty layouts:
<RelativeLayout
android:id="#+id/pluginsLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/mainButtons"
android:layout_below="#+id/paramsLayout">
<LinearLayout
android:id="#+id/capturePluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true">
</LinearLayout>
<LinearLayout
android:id="#+id/processingPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true">
</LinearLayout>
<LinearLayout
android:id="#+id/filterPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true">
</LinearLayout>
<LinearLayout
android:id="#+id/exportPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true">
</LinearLayout>
<RelativeLayout
android:id="#+id/viewfinderPluginLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true">
</RelativeLayout>
</RelativeLayout>
And like that I manage the size of adding views:
public void addVFPluginView(View view)
{
//Get maximum width and height for such plugins
int layoutHeight = this.getViewfinderLayoutHeight();
int layoutWidth = this.getViewfinderLayoutWidth();
//Calculate appropriate size of added plugin's view
android.widget.RelativeLayout.LayoutParams viewLayoutParams = (android.widget.RelativeLayout.LayoutParams)view.getLayoutParams();
viewLayoutParams = this.getTunedRelativeLayoutParams(view, viewLayoutParams, layoutWidth, layoutHeight);
//Get fixed maximum size for this plugin type
public int getViewfinderLayoutWidth()
{
return ((RelativeLayout)MainScreen.thiz.findViewById(R.id.pluginsLayout)).getWidth()/2;
}
public int getViewfinderLayoutHeight()
{
return (int)(((RelativeLayout)MainScreen.thiz.findViewById(R.id.pluginsLayout)).getHeight()*0.7);
}
((RelativeLayout)MainScreen.thiz.findViewById(R.id.viewfinderPluginLayout)).addView(view, viewLayoutParams);
}
android.widget.RelativeLayout.LayoutParams getTunedRelativeLayoutParams(View view, android.widget.RelativeLayout.LayoutParams currParams, int goodWidth, int goodHeight)
{
int viewHeight, viewWidth;
if(currParams != null)
{
viewHeight = currParams.height;
viewWidth = currParams.width;
if(viewHeight > goodHeight || viewHeight <= 0)
viewHeight = goodHeight;
if(viewWidth > goodWidth || viewWidth <= 0)
viewWidth = goodWidth;
currParams.width = viewWidth;
currParams.height = viewHeight;
view.setLayoutParams(currParams);
}
else
{
currParams = new android.widget.RelativeLayout.LayoutParams(goodWidth, goodHeight);
view.setLayoutParams(currParams);
}
return currParams;
}
Finally, next issue is for several views with suitable sizes but in sum they're bigger than allocated size. Maybe I'll just straightly count sizes of views and if the sum with the size of next adding view will be more than allocated size I just disallow to add this view.
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background"
android:orientation="vertical" >
<ScrollView
android:layout_width="wrap_content"
android:layout_height="fill_parent" >
<RelativeLayout
android:id="#+id/relativeLayout2"
android:layout_width="fill_parent"
android:layout_height="600dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
<include
android:id="#+id/include1"
android:layout_width="fill_parent"
android:layout_height="70dp"
layout="#layout/header_history" >
</include>
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#00000000"
android:divider="#android:color/black"
android:dividerHeight="1.0sp"
android:textColor="#000000" />
</RelativeLayout>
</ScrollView>
</RelativeLayout>
header_history
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/button" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#drawable/button"
android:gravity="left|center_vertical"
android:text=" History"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#android:color/white"
android:textSize="24sp"
android:textStyle="bold" />
</RelativeLayout>
I am trying to make my list view scrollable but it has become scrollable but I am unable to find the details of the list view. Please help me for the same. Friends,I have updated the header_history file also.
I've answered a question similar to this only. Here i explain you about why its not scrolling?
Simply, remove the ScrollView from your layout. And, make the LinearLayout as parent. And, try to run your app. It will scroll the list.
Because the ListView class implements its own scrolling and it just doesn't receive gestures because they all are handled by the parent ScrollView I strongly recommend you to simplify your layout somehow. For example you can add views you want to be scrolled to the ListView as headers or footers.
Have a look at this
See my existing answer
The problem is that you put a ListView in a ScrollView. The Android API says you should never ever put a scrollable element in another scrollable element.
If you need to to this anyway, you can solve the problem by subclassing the ListView and overwriting the onMeasure() method.
How can I put a ListView into a ScrollView without it collapsing?
http://nex-otaku-en.blogspot.de/2010/12/android-put-listview-in-scrollview.html
Edit: You use the following code to create a fully expanded list. Also it's worth to notice, that this might be a horrible idea for large list, due to performance reasons.
public class FullExpandedListView extends ListView {
public FullExpandedListView(Context context) {
super(context);
}
#Override
protected void onMeasure(int a, int b) {
super.onMeasure(a, b);
setListViewHeightBasedOnChildren();
}
private void setListViewHeightBasedOnChildren() {
SwfListAdapter listAdapter = (SwfListAdapter) getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
int desiredWidth = MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST);
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listControl);
listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listControl.getLayoutParams();
params.height = totalHeight + (listControl.getDividerHeight() * (listAdapter.getCount() - 1));
setLayoutParams(params);
}
}