在app背景中的Paralax效果

即时通讯新的Android世界。 我想在我的应用程序中放置一些视差背景效果。

我该怎么做? 如何在Android中解决这个问题?

有没有什么有效的方法来创build2-3层视差背景? Android API中是否有一些工具或类?

或者,也许我必须在代码中“手动”修改背景图像的位置或边距?

我使用API​​级别19。

我试图理解Paralloid库,但是这个太大了,没有任何解释就无法理解。 Im新的Android和Java,我不熟悉所有的布局和其他UI对象,但我熟悉MVC。

我开始赏金,也许有人可以一步一步地解释这个图书馆是如何工作的。

Solutions Collecting From Web of "在app背景中的Paralax效果"

这是你可以做的:

在你的activity / fragment布局文件中指定2个ScrollView的(比如background_sv和content_sv)。

<?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" > <com.example.parallax.MyScrollView android:id="@+id/background_sv" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/parallax_bg" android:layout_width="match_parent" android:layout_height="match_parent" android:background="..." /> </com.example.parallax.MyScrollView> <com.example.parallax.MyScrollView android:id="@+id/content_sv" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > </LinearLayout> </com.example.parallax.MyScrollView> </RelativeLayout> 

在背景高度的内容滚动视图中添加一个虚拟视图,并使其透明。 现在,将一个滚动监听器附加到content_sv。 当滚动内容滚动视图时,调用

 mBgScrollView.scrollTo(0, (int)(y /*scroll Of content_sv*/ / 2f)); 

现有的API没有获得滚动事件的支持。 因此,我们需要创build一个自定义滚动视图,以提供ScrollViewListener。

 package com.example.parallax; // imports; public class MyScrollView extends ScrollView { public interface ScrollViewListener { void onScrollChanged(MyScrollView scrollView, int x, int y, int oldx, int oldy); } private ScrollViewListener scrollViewListener = null; public MyScrollView(Context context) { super(context); } public MyScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public void setScrollViewListener(ScrollViewListener scrollViewListener) { this.scrollViewListener = scrollViewListener; } @Override protected void onScrollChanged(int x, int y, int oldx, int oldy) { super.onScrollChanged(x, y, oldx, oldy); if(scrollViewListener != null) { scrollViewListener.onScrollChanged(this, x, y, oldx, oldy); } } } 

这是承载内容ScrollView和背景ScrollView的活动

 package com.example.parallax; // imports; public class ParallaxActivity extends Activity implements ScrollViewListener { private MyScrollView mBgScrollView; private MyScrollView mContentScrollView; @Override public void onCreate(Bundle savedInstanceState) { mBgScrollView = findViewById(R.id.background_sv); mContentScrollView = findViewById(R.id.content_sv); mContentScrollView.setOnScrollListener(this); } @Override public void onScrollChanged(MyScrollView scrollView, int x, int y, int oldx, int oldy) { super.onScrollChanged(scrollView, x, y, oldx, oldy); // when the content scrollview will scroll by say 100px, // the background scrollview will scroll by 50px. It will // look like a parallax effect where the background is // scrolling with a different speed then the content scrollview. mBgScrollView.scrollTo(0, (int)(y / 2f)); } } 

我认为这个问题还不清楚,所以这不是一个真正的答案,而是一个比我可以在评论中包含更多细节的尝试。

我的问题是你想达到什么样的视差效果。 鉴于这三个例子(他们是演示应用程序,你可以从Play商店安装),如果有任何你想要的types的视差效果? 请在评论中回答。

  • Paralloid演示

  • 视差滚动演示

  • Google IO应用

给出答案,我们都会发现帮助更容易。 如果您编辑您的问题以包含此信息,则会得到改进。

以下包含Paralloid作者发布的示例应用程序:

https://github.com/chrisjenx/Paralloid/tree/master/paralloidexample

从“入门”部分下的GitHub页面:

布局

滚动型

这是一个例子,请参阅paralloidexample应用程序的完整代码。

 <FrameLayout ..> <FrameLayout android:id="@+id/top_content" android:layout_width="match_parent" android:layout_height="192dp"/> <uk.co.chrisjenx.paralloid.views.ParallaxScrollView android:id="@+id/scroll_view" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> <LinearLayout android:id="@+id/scroll_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingTop="192dp"/> </uk.co.chrisjenx.paralloid.views.ParallaxScrollView> </FrameLayout> 

分段

在你的onViewCreated()onCreateView()

 //... FrameLayout topContent = (FrameLayout) rootView.findViewById(R.id.top_content); ScrollView scrollView = (ScrollView) rootView.findViewById(R.id.scroll_view); if (scrollView instanceof Parallaxor) { ((Parallaxor) scrollView).parallaxViewBy(topContent, 0.5f); } // TODO: add content to top/scroll content 

而已!

查看Parallaxor界面,了解适用的视差方法。

希望这可以帮助!

此外, 这里是谷歌的Android入门页面的链接。

此外, 这里是一个“完整的初学者的Java教程”的链接。

以及关于布局的一些文档的链接 ,它们定义了用户界面的可视化结构。

话虽如此,您可以使用布局来定义接口的外观,并使用后续的示例代码来定义与它进行交互时会发生什么。

PS您可以在这里看到应用程序的行动

我使用ParallaxScroll库 。 非常容易使用,样品良好,有据可查。

这是如何使用ScrollView和它的背景图像。 我已经在github中提交了代码。

您需要扩展ScrollViewDrawable类。

  1. 默认情况下,ScrollView背景高度与视口高度相同。 为了实现视差效果,背景高度应该更大,并且应该基于ScrollView的子高度和我们要施加的背景滚动因子。 背景滚动因子为1表示背景高度与ScrollView子高度相同,因此背景将以与子滚动相同的偏移量滚动。 0.5表示背景高度是ScrollView子扩展高度的0.5倍,与子内容相比,滚动速度会减慢50%。 这有效地带来了视差滚动效果。

从ScrollView构造函数调用以下方法:

 void init() { // Calculate background drawable size before first draw of scrollview getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { // Remove the listener getViewTreeObserver().removeOnPreDrawListener(this); mDrawable = (ParallaxDrawable) getBackground(); if(mDrawable != null && mDrawable instanceof ParallaxDrawable) { // Get the only child of scrollview View child = getChildAt(0); int width = child.getWidth(); // calculate height of background based on child height and scroll factor int height = (int) (getHeight() + (child.getHeight() - getHeight()) * mScrollFactor); mDrawable.setSize(width, height); } return true; } }); } 
  1. 滚动ScrollView时,请在绘制背景时考虑滚动偏移量。 这基本上达到了视差效果。

ParallaxScrollView:

 protected void onScrollChanged(int x, int y, int oldX, int oldY) { if(mDrawable != null && mDrawable instanceof ParallaxDrawable) { // set the scroll offset for the background drawable. mDrawable.setScrollOffset(x*mScrollFactor, y*mScrollFactor); } } 

ParallaxDrawable:

 @Override public void draw(Canvas canvas) { // To move the background up, translate canvas by negative offset canvas.translate(-mScrollXOffset, -mScrollYOffset); mDrawable.draw(canvas); canvas.translate(mScrollXOffset, mScrollYOffset); } protected void onBoundsChange(Rect bounds) { // This sets the size of background drawable. mDrawable.setBounds(new Rect(bounds.top, bounds.left, bounds.left + mWidth, bounds.top + mHeight)); } 

ParallaxScrollView和ParallaxDrawable的用法:

 public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.parallax_layout); final ParallaxScrollView scrollView = (ParallaxScrollView) findViewById(R.id.sv); ParallaxDrawable drawable = new ParallaxDrawable(getResources().getDrawable(R.drawable.bg)); scrollView.setBackground( drawable, 0.2f ); } } 

parallax_layout.xml:

 <manish.com.parallax.ParallaxScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/sv" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:text="@string/text" /> <View android:layout_width="match_parent" android:layout_height="5dp" /> ... </LinearLayout> </manish.com.parallax.ParallaxScrollView> 

您可能已经注意到,Android API不支持很多具体的工具。 在API 20中,他们添加了作为深度属性的高程。 这不支持视差布局本身,但我认为这是Google的一个步骤,使这种工作更容易。 如果你想大胆猜测是否以及何时,我会说视差工具可以在API 25发布之前添加,基于最新的更新和电池效率的进展。

现在,您只需要倾听某种运动,并根据代表高程的值更改视图位置。

你的问题使我升级自己的项目,这是我在片段内使用ViewDragHelper。

 public class MainFragment extends Fragment implements View.OnTouchListener { private ImageView mDecor, mBamboo, mBackgroundBamboo; private RelativeLayout mRootLayout; private ViewDragHelper mDragHelper; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mRootLayout = (RelativeLayout) inflater.inflate(R.layout.fragment_main, container, false); mRootLayout.setOnTouchListener(this); mDecor = (ImageView) mRootLayout.findViewById(R.id.decor); mBamboo = (ImageView) mRootLayout.findViewById(R.id.bamboo); mBackgroundBamboo = (ImageView) mRootLayout.findViewById(R.id.backround_bamboo); mDragHelper = ViewDragHelper.create(mRootLayout, 1.0f, new ViewDragHelper.Callback() { private final float MAX_LEFT = -0; private final float MAX_TOP = -20; private final float MAX_RIGHT = 50; private final float MAX_BOTTOM = 10; private final float MULTIPLIER = 0.1f; private final int DECOR_ELEVATION = 3; private final int FRONT_BAMBOO_ELEVATION = 6; private final int BACKGROUND_BAMBOO_ELEVATION = 1; private float mLeft = 0; private float mTop = 0; @Override public boolean tryCaptureView(View view, int i) { return true; } @Override public int clampViewPositionVertical(View child, int top, int dy) { mTop += dy * MULTIPLIER; mTop = mTop > MAX_BOTTOM ? MAX_BOTTOM : mTop < MAX_TOP ? MAX_TOP : mTop; mDecor.setTranslationY(mTop * DECOR_ELEVATION); mBamboo.setTranslationY(mTop * FRONT_BAMBOO_ELEVATION); mBackgroundBamboo.setTranslationY(mTop * BACKGROUND_BAMBOO_ELEVATION); return 0; } @Override public int clampViewPositionHorizontal(View child, int left, int dx) { mLeft += dx * MULTIPLIER; mLeft = mLeft < MAX_LEFT ? MAX_LEFT : mLeft > MAX_RIGHT ? MAX_RIGHT : mLeft; mDecor.setTranslationX(mLeft * DECOR_ELEVATION); mBamboo.setTranslationX(mLeft * FRONT_BAMBOO_ELEVATION); mBackgroundBamboo.setTranslationX(mLeft * BACKGROUND_BAMBOO_ELEVATION); return 0; } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy){ mRootLayout.requestLayout(); } }); return mRootLayout; } @Override public boolean onTouch(View view, MotionEvent motionEvent) { mDragHelper.processTouchEvent(motionEvent); // you can still use this touch listener for buttons etc. return true; } }