package grimbo.android.demo.slidingmenu;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.HorizontalScrollView;
/**
* A HorizontalScrollView (HSV) implementation that disallows touch events (so no scrolling can be done by the user).
*
* This HSV MUST contain a single ViewGroup as its only child, and this ViewGroup will be used to display the children Views
* passed in to the initViews() method.
*/
public class MyHorizontalScrollView extends HorizontalScrollView {
public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public MyHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyHorizontalScrollView(Context context) {
super(context);
init(context);
}
void init(Context context) {
// remove the fading as the HSV looks better without it
setHorizontalFadingEdgeEnabled(false);
setVerticalFadingEdgeEnabled(false);
}
/**
* @param children
* The child Views to add to parent.
* @param scrollToViewIdx
* The index of the View to scroll to after initialisation.
* @param sizeCallback
* A SizeCallback to interact with the HSV.
*/
public void initViews(View[] children, int scrollToViewIdx, SizeCallback sizeCallback) {
// A ViewGroup MUST be the only child of the HSV
ViewGroup parent = (ViewGroup) getChildAt(0);
// Add all the children, but add them invisible so that the layouts are calculated, but you can't see the Views
for (int i = 0; i < children.length; i++) {
children[i].setVisibility(View.INVISIBLE);
parent.addView(children[i]);
}
// Add a layout listener to this HSV
// This listener is responsible for arranging the child views.
OnGlobalLayoutListener listener = new MyOnGlobalLayoutListener(parent, children, scrollToViewIdx, sizeCallback);
getViewTreeObserver().addOnGlobalLayoutListener(listener);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Do not allow touch events.
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// Do not allow touch events.
return false;
}
/**
* An OnGlobalLayoutListener impl that passes on the call to onGlobalLayout to a SizeCallback, before removing all the Views
* in the HSV and adding them again with calculated widths and heights.
*/
class MyOnGlobalLayoutListener implements OnGlobalLayoutListener {
ViewGroup parent;
View[] children;
int scrollToViewIdx;
int scrollToViewPos = 0;
SizeCallback sizeCallback;
/**
* @param parent
* The parent to which the child Views should be added.
* @param children
* The child Views to add to parent.
* @param scrollToViewIdx
* The index of the View to scroll to after initialisation.
* @param sizeCallback
* A SizeCallback to interact with the HSV.
*/
public MyOnGlobalLayoutListener(ViewGroup parent, View[] children, int scrollToViewIdx, SizeCallback sizeCallback) {
this.parent = parent;
this.children = children;
this.scrollToViewIdx = scrollToViewIdx;
this.sizeCallback = sizeCallback;
}
@Override
public void onGlobalLayout() {
// System.out.println("onGlobalLayout");
final HorizontalScrollView me = MyHorizontalScrollView.this;
// The listener will remove itself as a layout listener to the HSV
me.getViewTreeObserver().removeGlobalOnLayoutListener(this);
// Allow the SizeCallback to 'see' the Views before we remove them and re-add them.
// This lets the SizeCallback prepare View sizes, ahead of calls to SizeCallback.getViewSize().
sizeCallback.onGlobalLayout();
parent.removeViewsInLayout(0, children.length);
final int w = me.getMeasuredWidth();
final int h = me.getMeasuredHeight();
// System.out.println("w=" + w + ", h=" + h);
// Add each view in turn, and apply the width and height returned by the SizeCallback.
int[] dims = new int[2];
scrollToViewPos = 0;
for (int i = 0; i < children.length; i++) {
sizeCallback.getViewSize(i, w, h, dims);
// System.out.println("addView w=" + dims[0] + ", h=" + dims[1]);
children[i].setVisibility(View.VISIBLE);
parent.addView(children[i], dims[0], dims[1]);
if (i < scrollToViewIdx) {
scrollToViewPos += dims[0];
}
}
// For some reason we need to post this action, rather than call immediately.
// If we try immediately, it will not scroll.
new Handler().post(new Runnable() {
@Override
public void run() {
me.scrollBy(scrollToViewPos, 0);
}
});
}
}
/**
* Callback interface to interact with the HSV.
*/
public interface SizeCallback {
/**
* Used to allow clients to measure Views before re-adding them.
*/
public void onGlobalLayout();
/**
* Used by clients to specify the View dimensions.
*
* @param idx
* Index of the View.
* @param w
* Width of the parent View.
* @param h
* Height of the parent View.
* @param dims
* dims[0] should be set to View width. dims[1] should be set to View height.
*/
public void getViewSize(int idx, int w, int h, int[] dims);
}
}
在Android开发中,系统美化是提升用户体验的重要环节。本教程主要关注如何实现一个仿Facebook的布局效果,这在社交应用中非常常见,可以提供类似新闻 feed 的流畅滚动体验。通过学习这一主题,开发者将深入理解Android自定义视图、布局管理器以及动画的设计与实现。 "2021-系统美化-Android 仿facebook布局效果.zip" 包含的源码为我们提供了一个实际的示例,用于展示如何在Android应用中复制Facebook的界面风格。这个项目可能包括了自定义的RecyclerView适配器、自定义的ItemDecoration(用于添加分割线)以及自定义的布局管理器,如LinearLayoutManager或GridLayoutManager的变体,来实现特定的滚动效果。 1. 自定义视图:在Android中,我们经常需要为特定需求创建自定义视图。这通常涉及继承View或ViewGroup,并重写onDraw()方法来绘制自己的图形。在Facebook布局中,可能会有一个自定义的CardView来模拟信息卡片的外观,包括圆角、阴影等效果。 2. RecyclerView:Facebook的布局大量使用了RecyclerView,它是一种高效的数据列表视图,可以处理大量的数据项并实现流畅的滚动。开发者需要自定义RecyclerView.Adapter和ViewHolder,以便展示不同的内容类型,如文字、图片、视频等。 3. 布局管理器:Facebook的布局效果可能涉及到自定义布局管理器,以实现瀑布流、平铺或混合排列的效果。例如,自定义LinearLayoutManager可以实现不同大小卡片的错落布局。 4. 动画效果:Facebook界面中的滚动和交互通常包含丰富的动画效果,如加载更多时的下拉刷新动画,或者在滚动过程中图片的懒加载和渐显效果。开发者需要掌握Property Animation或ViewPropertyAnimator来实现这些高级动画。 5. 数据绑定和响应式编程:为了使布局与数据模型保持同步,开发者可能使用了Data Binding库或者MVVM架构模式,这使得UI可以直接响应数据的变化,提高代码的可维护性。 6. 图片加载库:为了优化性能和用户体验,开发者通常会使用如Glide或Picasso这样的第三方库来加载和缓存网络图片,确保在用户滚动时快速显示。 7. 材质设计:虽然这个主题主要关注仿Facebook的布局,但Android开发者也需要了解和遵循Google的材质设计指南,以保证应用的视觉一致性。 通过研究和分析这个项目,开发者不仅能学到如何实现一个仿Facebook的布局,还能提升在Android UI设计、性能优化和用户体验方面的技能。对于想要从事Android应用开发的人来说,这是一个很好的实践案例,可以帮助他们更好地理解和运用Android系统的各项功能。
- 1
- #完美解决问题
- #运行顺畅
- #内容详尽
- #全网独家
- #注释完整
- 粉丝: 3206
- 资源: 1万+
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 这是一个筛选菜单库,开发者只需要填充数据即可,在很多App上都能看到这个效果,如美团,爱奇艺,大众点评等.zip
- Flask Web应用程序与PostgreSQL数据库集成实现API及自动化脚本构建工具
- 这是一个运动健身类app,纺大夜跑团 ,能够根据gps或网络定位来实时绘制跑步轨迹; (毕业设计 后台管理系统 学生管理系统 教务管理系统 学校管理系统 毕设 管理平台 数据管理系统 后端开发.zip
- html+css网页设计 美食 美食模版2个页面
- 遥感大数据012345.zip
- 阿里天池比赛 印象盐城·数创未来大数据竞赛 - 盐城汽车上牌量预测.zip
- 阿里巴巴天池大数据竞赛.zip
- 零代,项目脚手架,包括Web应用、WebApi接口、微服务、控制台、定时调度任务、大数据计算、物联网等项目模板.zip
- chrome 原生 netlog抓去
- 零基础大数据学习笔记.zip
- 高并发但每次爬取数据量不大的分布式爬虫 .zip
- 机械设计笔记本电脑自动搬运压合测试站sw16非常好的设计图纸100%好用.zip
- simulink 双馈风机稳态模型 包含最大功率跟踪控制,MPPT,参数可调 (1)转子侧变器采用基于定子电压定向的矢量控制策略,可以有功无功解耦,具备MPPT能力,采用功率外环电流内环双闭环控制结构
- 浪潮端到端产品安全保障体系:2021年度网络安全实践与展望
- Fluent的颗粒流 稀疏颗粒常使用DPM模型进行解决 不考虑颗粒碰撞变形,但考虑颗粒之间的碰撞行为,可以使用欧拉颗粒流模型 考虑颗粒碰撞摩擦以及变形,可以使用其内置的DEM模型,也可以采用与其他D
- python入门教程资源