[置顶] Android ViewPage+Fragment伸缩实现菜单效果,仿Ifanr
2016-09-22 22:12
549 查看
先上Ifanr效果
实现效果
1.布局xml
设置android:clipChildren=”false” 使子View在ViewPage被缩放时允许超出ViewPage的范围
activity_main.xml
fragment_first_layout.xml
背景菜单布局
menuview_background.xml
2.MainActivity
3.BaseFragment
4.自定义ViewPage
需要对触摸事件进行转发拦截等
最后老规矩上链接GitHub
实现效果
1.布局xml
设置android:clipChildren=”false” 使子View在ViewPage被缩放时允许超出ViewPage的范围
activity_main.xml
<?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" android:id="@+id/content" tools:context=".View.Activity.MainActivity"> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" android:fillViewport="false" /> <android.support.v4.widget.SwipeRefreshLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/tabs"> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:id="@+id/frag_content" android:clipChildren="false" android:foreground="@android:color/transparent"> <include layout="@layout/menuview_background" ></include> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/vp_content" android:clipChildren="false"> <com.gy.ifanr.View.Widget.MyViewPage android:id="@+id/view_pager" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/black" android:clipChildren="false" android:layout_alignParentBottom="true"/> </FrameLayout> <ImageButton android:id="@+id/btn_scale" android:layout_width="45dp" android:layout_height="45dp" android:layout_margin="10dp" android:background="@drawable/menu" android:layout_gravity="right|top" android:clickable="true" android:focusable="true"/> <ImageButton android:id="@+id/btn_menu" android:layout_width="45dp" android:layout_height="45dp" android:layout_margin="10dp" android:background="@drawable/circle" android:layout_gravity="left|top" android:clickable="true" android:focusable="true"/> </FrameLayout> </android.support.v4.widget.SwipeRefreshLayout> </RelativeLayout>
fragment_first_layout.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="你好" android:id="@+id/hello" android:textColor="@android:color/black"/> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/mask" android:background="@android:color/transparent"/> </FrameLayout>
背景菜单布局
menuview_background.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imageView" android:src="@mipmap/ic_launcher"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="菜单1" android:id="@+id/textView" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="菜单2" android:id="@+id/textView2" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="菜单3" android:id="@+id/textView3" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="菜单4" android:id="@+id/textView4" /> </LinearLayout>
2.MainActivity
public class MainActivity extends AppCompatActivity implements Animator.AnimatorListener,View.OnClickListener, OnFragmentClick { private List<Fragment> fragments; private MyViewPage viewPager; private RelativeLayout content; private TabLayout mTabLayout; private FrameLayout viewpagecontent; private FrameLayout vpParent; private float scale = 0.6f; private float x,y; private ImageButton menubt,scalebt; private boolean scalling = false; private boolean isScalled = false; private MenuHelper moremenu; private View moremenuView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findview(); addFrags(); setView(); } private void findview(){ viewPager = (MyViewPage) findViewById(R.id.view_pager); content = (RelativeLayout) findViewById(R.id.content); viewpagecontent = (FrameLayout) findViewById(R.id.frag_content); mTabLayout = (TabLayout) findViewById(R.id.tabs); vpParent = (FrameLayout) findViewById(R.id.vp_content); menubt = (ImageButton) findViewById(R.id.btn_menu); scalebt = (ImageButton) findViewById(R.id.btn_scale); moremenuView = View.inflate(this,R.layout.grid_menu_layout,null); } private void setView(){ viewPager.setOffscreenPageLimit(3); viewPager.setPageMargin(6); menubt.setOnClickListener(this); scalebt.setOnClickListener(this); moremenu = new MenuHelper(this,menubt,moremenuView,viewpagecontent); //将ViewPage父容器的touch事件转发给ViewPage,不然只有中间的item可以触摸,并且需要自定义 //ViewPage vpParent.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return viewPager.dispatchTouchEvent(event); } }); } private void addFrags(){ List<String> titles = new ArrayList<>(); titles.add("页面1"); titles.add("页面2"); titles.add("页面3"); mTabLayout.addTab(mTabLayout.newTab().setText(titles.get(0))); mTabLayout.addTab(mTabLayout.newTab().setText(titles.get(1))); mTabLayout.addTab(mTabLayout.newTab().setText(titles.get(2))); fragments = new ArrayList<>(); fragments.add(new FirstFragment()); fragments.add(new SecFragment()); fragments.add(new ThrFragment()); FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager(), fragments, titles); viewPager.setAdapter(adapter); mTabLayout.setupWithViewPager(viewPager); mTabLayout.setTabsFromPagerAdapter(adapter); } //对ViewPage的父视图进行Y轴缩放,同时对ViewPage进行X轴缩放,保持x/y比例 private void scaleViewPage(){ x = vpParent.getWidth()/2 + vpParent.getX(); y = vpParent.getHeight() + vpParent.getY(); ViewPropertyAnimator.animate(vpParent).setListener(this).scaleY(scale); ViewPropertyAnimator.animate(viewPager).scaleX(scale); ViewHelper.setPivotX(viewPager, x); ViewHelper.setPivotY(viewPager, y); ViewHelper.setPivotX(vpParent, x); ViewHelper.setPivotY(vpParent, y); ViewHelper.setScaleX(viewPager,scale); ViewHelper.setScaleY(vpParent,scale); } //缩放还原 private void restoreViewPage(){ x = vpParent.getWidth()/2 + vpParent.getX(); y = vpParent.getHeight() + vpParent.getY(); ViewPropertyAnimator.animate(vpParent).setListener(this).scaleY(1); ViewPropertyAnimator.animate(viewPager).scaleX(1); ViewHelper.setPivotX(viewPager, x); ViewHelper.setPivotY(viewPager, y); ViewHelper.setPivotX(vpParent, x); ViewHelper.setPivotY(vpParent, y); ViewHelper.setScaleX(viewPager,1); ViewHelper.setScaleY(vpParent,1); } //相关视图元素进行控制 @Override public void onAnimationStart(Animator animator) { scalling = true; if (!isScalled){ mTabLayout.setVisibility(View.INVISIBLE); menubt.setVisibility(View.GONE); } } @Override public void onAnimationEnd(Animator animator) { scalling = false; isScalled = !isScalled; if (!isScalled){ mTabLayout.setVisibility(View.VISIBLE); menubt.setVisibility(View.VISIBLE); } } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_scale: doScale(); break; case R.id.btn_menu: moremenu.showMenu(); break; } } private void doScale() { if (scalling) return; if (isScalled){ restoreViewPage(); }else { scaleViewPage(); } } @Override public void OnFragClick(int no) { if (isScalled){ viewPager.setCurrentItem(no); doScale(); } } }
3.BaseFragment
/** * 基类Fragment,捕获Click事件以收起菜单 * Created by gy939 on 2016/9/21. */ public abstract class BaseFragment extends Fragment{ private View view; private OnFragmentClick fragmentClick; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_first_layout,container,false); //这里其实建议使用类似EventBus的消息框架做组件间通讯。 fragmentClick = (OnFragmentClick) getActivity(); view.findViewById(R.id.mask).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e("gy","点击了"+hashCode()); fragmentClick.OnFragClick(getNo()); } }); ((TextView)view.findViewById(R.id.hello)).setText(getClass().getName()); return view; } //获取Fragment编号 protected abstract int getNo(); }
4.自定义ViewPage
需要对触摸事件进行转发拦截等
public class MyViewPage extends ViewPager{ public MyViewPage(Context context) { super(context); } public MyViewPage(Context context, AttributeSet attrs) { super(context, attrs); } /** * 拦截ViewPage范围以外的Touch事件 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { FragmentAdapter adapter = (FragmentAdapter) getAdapter(); int[] xy = new int[2]; getLocationInWindow(xy); int x = xy[0]; int y = xy[1]; Log.e("gy","x="+x+"y="+y); if (ev.getRawY() < y){ Log.e("gy",y+"-"+ev.getRawY()); return true; } if (getWidth() - x < ev.getRawX()){ //在右边 Log.e("gy","右边"); return true; }else if (x > ev.getRawX()){ //在左边 Log.e("gy","左边"); return true; }else { //中间在区域内不做拦截 } return super.onInterceptTouchEvent(ev); } /** * 向ViewPage范围以外的子View分发Touch事件, * 因为设置了ClipChildren属性以后,子View已经可以超出父View的范围了 */ @Override public boolean onTouchEvent(MotionEvent ev) { FragmentAdapter adapter = (FragmentAdapter) getAdapter(); int fragno = adapter.getCurPosition(); int[] xy = new int[2]; getLocationInWindow(xy); int x = xy[0]; int y = xy[1]; if (getWidth() - x < ev.getRawX()){ //在右边 Log.e("gy","右边"); //在右边将事件分发给当前Page的右边一个Page if (fragno < adapter.getCount() - 1) adapter.getItem(fragno + 1).getView().dispatchTouchEvent(ev); }else if (x > ev.getRawX()){ //在左边 Log.e("gy","左边"); //在左边边将事件分发给当前Page的左边一个Page if (fragno > 0) adapter.getItem(fragno - 1).getView().dispatchTouchEvent(ev); }else { //中间 } return super.onTouchEvent(ev); } }
最后老规矩上链接GitHub
相关文章推荐
- Android实现伸缩弹力分布菜单效果
- Android实现伸缩弹力分布菜单效果
- Android实现伸缩弹力分布菜单效果的示例
- Android实现伸缩弹力分布菜单效果
- JS实现横向拉伸动感伸缩菜单效果代码
- 基于jQuery实现手风琴菜单、层级菜单、置顶菜单、无缝滚动效果
- Android实现伸缩弹力分布菜单效果
- jquery实现可点击伸缩与展开的菜单效果代码
- 基于C#实现的仿windows左侧伸缩菜单效果
- Android实现伸缩弹力分布菜单效果
- Android实现伸缩弹力分布菜单效果
- Android实现伸缩弹力分布菜单效果
- jquery实现可点击伸缩与展开的菜单效果代码
- jQuery实现的经典竖向伸缩菜单效果代码
- Android实现伸缩弹力分布菜单效果
- jQuery实现的经典竖向伸缩菜单效果代码
- Android实现伸缩弹力分布菜单效果
- [置顶] 利用自定义View结合onTouchListener实现QQ侧滑菜单效果
- 【转】Android实现伸缩弹力分布菜单效果
- Android实现伸缩弹力分布菜单效果