自定义抽屉菜单
package com.bwie.slidingmenu;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
/**
* 自定义抽屉
* */
public class SlidingView extends FrameLayout {
private LinearLayout contentLinear;//显示主界面
private LinearLayout menuLinear;//显示菜单
private int width = 400;//menu菜单宽度为400px
private PointF lastPointF = new PointF();
//上一次采集到的手指在屏幕上出发的点(X,Y)xy类型float
public SlidingView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
//初始化抽屉主界面布局
contentLinear = new LinearLayout(getContext());
FrameLayout.LayoutParams contentLp = new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
contentLinear.setOrientation(LinearLayout.VERTICAL);
contentLinear.setLayoutParams(contentLp);
contentLinear.setBackgroundColor(Color.RED);
addView(contentLinear);
//初始化顶部菜单布局
menuLinear = new LinearLayout(getContext());
FrameLayout.LayoutParams menuLp = new FrameLayout.LayoutParams(
width, LayoutParams.MATCH_PARENT);
menuLp.leftMargin = -width;
menuLinear.setOrientation(LinearLayout.VERTICAL);
menuLinear.setLayoutParams(menuLp);
menuLinear.setBackgroundColor(Color.GREEN);
addView(menuLinear);
}
//向content中添加要显示的view
public void addContent(View view){
if (view == null)
return;
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT
);
view.setLayoutParams(lp);
contentLinear.addView(view);
}
//向menu中添加要显示的view
public void addMenu(View view){
if (view == null)
return;
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT
);
view.setLayoutParams(lp);
menuLinear.addView(view);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN){
//手指按下
//获取按下的点
lastPointF.x = ev.getX();
lastPointF.y = ev.getY();
}else if (ev.getAction() == MotionEvent.ACTION_MOVE){
//手指移动
PointF pointF = new PointF(ev.getX(),ev.getY());
//获取X轴滑动距离
float distanceX = Math.abs(pointF.x - lastPointF.x);
//获取Y轴滑动距离
float distanceY = Math.abs(pointF.y - lastPointF.y);
//区分垂直水平滑动方向
if ((2*distanceY)>distanceX){
//垂直滑动->分发事件
return super.dispatchTouchEvent(ev);
}
if (distanceX>=10) {
//获取菜单布局管理器
FrameLayout.LayoutParams lp = (LayoutParams) menuLinear.getLayoutParams();
//区分左右滑动方向
if ((pointF.x-lastPointF.x)<0){
//从右向左
distanceX = -distanceX;
}
//可滑动区间内->更新leftmargin
lp.leftMargin = (int) (lp.leftMargin + distanceX);
if (lp.leftMargin > 0) {
lp.leftMargin = 0;
//重新布局
return true;
}
if (lp.leftMargin < -width) {
lp.leftMargin = -width;
return true;
}
menuLinear.requestLayout();
lastPointF.x = pointF.x;
lastPointF.y = pointF.y;
}
}else if (ev.getAction() == MotionEvent.ACTION_UP){
//手指抬起
FrameLayout.LayoutParams lp = (LayoutParams) menuLinear.getLayoutParams();
if (lp.leftMargin<-width/2){
lp.leftMargin = -width;
}else {
lp.leftMargin = 0;
}
menuLinear.requestLayout();
}
return super.dispatchTouchEvent(ev);
}
}
public class MainActivity extends AppCompatActivity {
private SlidingView slidingView;
private View menuView;
private View contentView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init(){
slidingView = findViewById(R.id.slidingmenu);
menuView = LayoutInflater.from(this).inflate(R.layout.layout_menu,null);
contentView = LayoutInflater.from(this).inflate(R.layout.layout_content,null);
slidingView.addContent(contentView);
slidingView.addMenu(menuView);
}
}
自定义下拉刷新
- 基于自定义view上下啦刷新;
- 项目中使用上下啦刷新作用:刷新数据;数据分页;
- 基于系统framelayout编写上下拉刷新效果;
- 为什么基于framelayout->布局->framelayout中可添加子布局
-> 可向framelayout中添加支持上下拉刷新的列表 - 实现步骤:
(1)->创建PulltorefreshLayout自定义view->继承framelayout
(2)->创建头布局->默认添加到自定义view中
(3)->获取自定义view中包含的recyclerview->view
(4)->获取的子view转化为具体类型->RecyclerView
(5)->分发方法中拦截touch拦截
----->RecyclerView处于最上一条
----->手指由上向下滑动
----->下拉刷新->默认状态
------------->下拉刷新状态
------------->释放刷新状态
------------->正在刷新状态->回调接口->Activity中->网络请求->关闭下拉刷新
----->手指由下向上滑动->分发touch事件->保证Recyclerview可正常滑动
----->手指水平滑动->分发touch事件
自定义下拉刷新
import android.content.Context;
import android.graphics.Color;
import android.graphics.PointF;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* 自定义下拉刷新控件
* */
public class PulltoRefreshLayout extends FrameLayout {
private LinearLayout headLinear;//头布局的布局容器
private RecyclerView rv;//FrameLayout中显示的列表
private TextView headTv;
private final static int PULL = 1;//下拉状态
private final static int RELASE = 2;//释放刷新
private final static int LOADING = 3;//正在刷新
private final static int DEFAULT = 4;//默认
private int mode = DEFAULT;//当前自定义控件的模式
private PointF lastPointF = new PointF();//手指在屏幕中上一次触摸的点
private boolean topFlag = true;//RecyclerView是否滑动到顶部标志
private int height = 0;//headview头布局高度->下拉刷新临界值->添加高度的倍数作为临界值->增加滑动距离防止用户误触造成不必要刷新
private LoadingListener loadingListener;//正在刷新回调接口
public PulltoRefreshLayout( Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
//初始化
private void init(){
headLinear = new LinearLayout(getContext());
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT
);
headLinear.setLayoutParams(layoutParams);
headLinear.setOrientation(LinearLayout.VERTICAL);
addView(headLinear);
// //循环遍历framelayout中全部子布局
// for (int i = 0;i < getChildCount();i ++){
// View view = getChildAt(i);
// if (view instanceof RecyclerView){
// rv = (RecyclerView) view;
// break;
// }
// }
// rv.addOnScrollListener(new RvListener());
}
public void setRV(RecyclerView rv){
this.rv = rv;
this.rv.setBackgroundColor(Color.WHITE);
this.rv.addOnScrollListener(new RvListener());
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
this.rv.setLayoutParams(lp);
addView(rv);
}
//分发方法
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN){
lastPointF.x = ev.getX();
lastPointF.y = ev.getY();
}else if (ev.getAction() == MotionEvent.ACTION_MOVE){
PointF pointF = new PointF(ev.getX(),ev.getY());
float disX = pointF.x - lastPointF.x;
float disY = pointF.y - lastPointF.y;
if (Math.abs(disX)>Math.abs(disY*2)){
//水平滑动
return super.dispatchTouchEvent(ev);
}
//RecyclerView未置顶
if (!topFlag)
return super.dispatchTouchEvent(ev);
//RecyclerView在顶部->从下向上滑动->用户想浏览RecyclerView
//->从上向下滑动->用户想下拉刷新
//从下向上滑动
if (disY < 0 && mode == DEFAULT){
topFlag = false;//改变recyclerView置顶标志
return super.dispatchTouchEvent(ev);
}
if (Math.abs(disY)>5) {
//下拉刷新操作->下拉刷新逻辑处理
selMode(disY);
}
return true;
}else if (ev.getAction() == MotionEvent.ACTION_UP){
if (mode == PULL || mode == DEFAULT){
mode = DEFAULT;
// headTv.setText("下拉刷新");
}
if (mode == RELASE)
mode = LOADING;
if (mode == LOADING && loadingListener !=null){
loadingListener.loading();
FrameLayout.LayoutParams lp = (LayoutParams) rv.getLayoutParams();
lp.topMargin = height;
headTv.setText("正在刷新");
rv.requestLayout();
}else {
FrameLayout.LayoutParams lp = (LayoutParams) rv.getLayoutParams();
lp.topMargin = 0;
rv.requestLayout();
}
}
return super.dispatchTouchEvent(ev);
}
//下拉刷新选择状态方法
private void selMode(float disY){
FrameLayout.LayoutParams lp = (LayoutParams) rv.getLayoutParams();
lp.topMargin += disY;
if (lp.topMargin < 0)
lp.topMargin = 0;
if (lp.topMargin > 3*height)
lp.topMargin = 3*height;
//切换下拉状态->下拉刷新状态->0-(3*height-10);释放刷新(3*height-10 3*height)
if (lp.topMargin > 0 && lp.topMargin < (3*height-10)){
mode = PULL;
headTv.setText("下拉刷新");
}else if (lp.topMargin > (3*height-10)){
mode = RELASE;
headTv.setText("释放刷新");
}
rv.requestLayout();
Log.e("####","selMode->"+mode);
}
//设置headView方法
public void addHeadView(View view){
view.measure(0,0);
height = view.getMeasuredHeight();
view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
view.getMeasuredHeight()));
headLinear.addView(view);
headTv = view.findViewById(R.id.tv);
}
//设置下拉刷新监听方法
public void setLoadingListener(LoadingListener loadingListener){
this.loadingListener = loadingListener;
}
//完成方法->加载完网络请求数据->关闭下拉刷新
public void complate(){
mode = DEFAULT;
topFlag = true;
FrameLayout.LayoutParams lp = (LayoutParams) rv.getLayoutParams();
lp.topMargin = 0;
rv.requestLayout();
}
//监听RecyclerView滑动位置->是否滑动到顶部
private class RvListener extends RecyclerView.OnScrollListener{
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
Log.e("####","RvListener->onScrolled");
if (!recyclerView.canScrollVertically(-1)&&!topFlag){
Log.e("####","RvListener->onScrolled->滑动到顶部");
topFlag = true;
}
}
}
//正在刷新回调监听器
public interface LoadingListener{
void loading();
}
}
适配器
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.MainVH>{
private List<String>list;
public MainAdapter(List<String>list){
this.list = list;
}
@NonNull
@Override
public MainVH onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_main,viewGroup,false);
return new MainVH(itemView);
}
@Override
public void onBindViewHolder(@NonNull MainVH mainVH, int i) {
mainVH.tv.setText(list.get(i));
}
@Override
public int getItemCount() {
return list.size();
}
class MainVH extends RecyclerView.ViewHolder{
TextView tv;
public MainVH(@NonNull View itemView) {
super(itemView);
tv = itemView.findViewById(R.id.main_tv);
}
}
}
activity
public class MainActivity extends AppCompatActivity implements PulltoRefreshLayout.LoadingListener {
private List<String>list = new ArrayList<>();
private PulltoRefreshLayout pullLayout;
private RecyclerView rv;
private View headView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
init();
}
private void init(){
pullLayout = findViewById(R.id.main_pull);
rv = new RecyclerView(this);
pullLayout.setRV(rv);
headView = LayoutInflater.from(this).inflate(R.layout.layout_head,null);
pullLayout.addHeadView(headView);
pullLayout.setLoadingListener(this);
LinearLayoutManager manager = new LinearLayoutManager(this);
manager.setOrientation(LinearLayoutManager.VERTICAL);
rv.setLayoutManager(manager);
rv.setAdapter(new MainAdapter(list));
}
private void initData(){
for (int i = 0;i < 100;i ++){
list.add("item:"+i);
}
}
@Override
public void loading() {
new Thread(){
@Override
public void run() {
super.run();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
pullLayout.complate();
}
});
}
}.start();
}
}