2024年最新Android TagFlowLayout完全解析 一款针对Tag的布局,京东面试题答案

最后

简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。

选定你想去的几家公司后,先去一些小的公司练练,学习下面试技巧,总结下,也算是熟悉下面试氛围,平时和同事或者产品PK时可以讲得头头是道,思路清晰至极,到了现场真的不一样,怎么描述你所做的一切,这绝对是个学术性问题!

面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。

金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

if (child != null)

{

doSelect(child, pos);

if (mOnTagClickListener != null)

{

return mOnTagClickListener.onTagClick(child.getTagView(), pos, this);

}

}

return super.performClick();

}

private TagView findChild(int x, int y)

{

final int cCount = getChildCount();

for (int i = 0; i < cCount; i++)

{

TagView v = (TagView) getChildAt(i);

if (v.getVisibility() == View.GONE) continue;

Rect outRect = new Rect();

v.getHitRect(outRect);

if (outRect.contains(x, y))

{

return v;

}

}

return null;

}

可以看到我们这里巧妙的利用了performClick这个回调,来确定的确是触发了click事件,而不是自己去判断什么算click的条件。但是呢,我们的performClick没有提供MotionEvent的参数,不过不要紧,我们都清楚click的事件发生在ACTION_UP之后,所以我们提供一个变量去记录最后一次触发ACTION_UP的mMotionEvent。

我们在performClick里面,根据mMotionEvent,去查找是否落在某个子View身上,如果落在,那么就确定点击在它身上了,直接回调即可,关于接口的定义如下,(ps:关于doSelect方法,我们后面说):

public interface OnTagClickListener

{

boolean onTagClick(View view, int position, FlowLayout parent);

}

private OnTagClickListener mOnTagClickListener;

public void setOnTagClickListener(OnTagClickListener onTagClickListener)

{

mOnTagClickListener = onTagClickListener;

if (onTagClickListener != null) setClickable(true);

}

可以看到,如果设置了setOnTagClickListener,我们显示的设置了父ViewsetClickable(true)。以防万一父View不具备消费事件的能力。


四、全面支持Checked


这一节呢,主要包含支持几个功能:

* 直接设置selector为background即可完成标签选则的切换,类似CheckBox

* 支持控制选择的Tag数量,比如:单选、多选

* 支持setOnSelectListener,当选择某个Tag后回调

首先,我们提供了两个自定义的属性,multi_suppoutmax_select。一个是指出是否支持选择(如果为false,意味着你只能通过setOnTagClickListener去做一些操作),一个是设置最大的选择数量,-1为不限制数量。

ok,那么核心的代码依然在performClick中被调用的:

@Override

public boolean performClick()

{

//省略了一些代码…

doSelect(child, pos);

if (mOnTagClickListener != null)

{

return mOnTagClickListener.onTagClick(child.getTagView(), pos, this);

}

//省略了一些代码…

}

private void doSelect(TagView child, int position)

{

if (mSupportMulSelected)

{

if (!child.isChecked())

{

if (mSelectedMax > 0 && mSelectedView.size() >= mSelectedMax)

return;

child.setChecked(true);

mSelectedView.add(position);

} else

{

child.setChecked(false);

mSelectedView.remove(position);

}

if (mOnSelectListener != null)

{

mOnSelectListener.onSelected(new HashSet(mSelectedView));

}

}

}

ok,可以看到,如果点击了某个标签,进入doSelect方法,首先判断你是否开启了多选的支持(默认支持),然后判断当前的View是否是非Checked的状态,如果是非Checked状态,则判断最大的选择数量,如果没有达到,则设置checked=true,同时加入已选择的集合;反之已经是checked状态,就是取消选择状态了。同时如果设置了mOnSelectListener,回调一下。

ok,其实这里隐藏了一些东西,关于接口回调我们不多赘述了,大家都明白。这里主要看Checked。首先你肯定有几个问题:

  • childView哪来的isChecked(),setChecked()方法?

  • 这么做就能改变UI了?

下面我一一解答:首先,我们并非知道adapter#getView返回的是什么View,但是可以肯定的是,大部分View都是没有isChecked(),setChecked()方法的。但是我们需要有,怎么做?还记得我们setAdapter的时候,给getView外层包了一层TagView么,没错,就是TagView起到的作用:

package com.zhy.view.flowlayout;

import android.content.Context;

import android.view.View;

import android.widget.Checkable;

import android.widget.FrameLayout;

/**

  • Created by zhy on 15/9/10.

*/

public class TagView extends FrameLayout implements Checkable

{

private boolean isChecked;

private static final int[] CHECK_STATE = new int[]{android.R.attr.state_checked};

public TagView(Context context)

{

super(context);

}

public View getTagView()

{

return getChildAt(0);

}

@Override

public int[] onCreateDrawableState(int extraSpace)

{

int[] states = super.onCreateDrawableState(extraSpace + 1);

if (isChecked())

{

mergeDrawableStates(states, CHECK_STATE);

}

return states;

}

/**

  • Change the checked state of the view

  • @param checked The new checked state

*/

@Override

public void setChecked(boolean checked)

{

if (this.isChecked != checked)

{

this.isChecked = checked;

refreshDrawableState();

}

}

/**

  • @return The current checked state of the view

*/

@Override

public boolean isChecked()

{

return isChecked;

}

/**

  • Change the checked state of the view to the inverse of its current state

*/

@Override

public void toggle()

{

setChecked(!isChecked);

}

}

我们的TagView实现了Checkable接口,所以提供了问题一的方法。

下面解释问题二: 这么做就能改变UI了?

我们继续看TagView这个类,这个类中我们复写了onCreateDrawableState,在里面添加了CHECK_STATE的支持。当我们调用setChecked方法的时候,我们会调用refreshDrawableState()来更新我们的UI。

但是你可能又会问了,你这个是TagView支持了CHECKED状态,关它的子View什么事?我们的background可是设置在子View上的。

没错,这个问题问的相当好,你还记得我们在setAdapter,addView之前有一行非常核心的代码:#mAdapter.getView().setDuplicateParentStateEnabled(true);setDuplicateParentStateEnabled这个方法允许我们的CHECKED状态向下传递。

到这,你应该明白了吧~~

所以我们对于UI的变化,只需要设置View的Backgroud为:

<?xml version="1.0" encoding="utf-8"?>

<item

android:drawable=“@drawable/checked_bg”

android:state_checked=“true”>

这样,如果你的设计稿发生变化,大部分情况下,你只需要改改xml文件就可以了。

ok,到此我们的核心部分的剖析就结束了,接下来贴贴用法:


五、用法


用法其实很简单,大家可以参考例子,我这里大致贴一下:

(1)设置数据

mFlowLayout.setAdapter(new TagAdapter(mVals)

{

@Override

public View getView(FlowLayout parent, int position, String s)

{

TextView tv = (TextView) mInflater.inflate(R.layout.tv,

mFlowLayout, false);

tv.setText(s);

return tv;

}

});

getView中回调,类似ListView等用法。

(2)对于选中状态

你还在复杂的写代码设置选中后标签的显示效果么,翔哥说No!

<?xml version="1.0" encoding="utf-8"?>

<item android:color=“@color/tag_select_textcolor”

android:drawable=“@drawable/checked_bg”

android:state_checked=“true”>

设置个background,上面一个状态为android:state_checked,另一个为正常。写写布局文件我都嫌慢,怎么能写一堆代码控制效果,设置改个效果,岂不是没时间dota了。

(3)事件

mFlowLayout.setOnTagClickListener(new TagFlowLayout.OnTagClickListener()

{

@Override

public boolean onTagClick(View view, int position, FlowLayout parent)

{

Toast.makeText(getActivity(), mVals[position], Toast.LENGTH_SHORT).show();

return true;

}

});

点击标签时的回调。

mFlowLayout.setOnSelectListener(new TagFlowLayout.OnSelectListener()

{

@Override

public void onSelected(Set selectPosSet)

{

getActivity().setTitle(“choose:” + selectPosSet.toString());

}

});

选择多个标签时的回调。

最后肯定有人会问,支持字体变色吗?ScrollView会冲突吗?

附上最新效果图:

大家就自行查看源码了。

最后,源码下载地址:https://github.com/hongyangAndroid/FlowLayout


总结

Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

上面分享的字节跳动公司2020年的面试真题解析大全,笔者还把一线互联网企业主流面试技术要点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

就先写到这,码字不易,写的很片面不好之处敬请指出,如果觉得有参考价值的朋友也可以关注一下我

①「Android面试真题解析大全」PDF完整高清版+②「Android面试知识体系」学习思维导图压缩包阅读下载,最后觉得有帮助、有需要的朋友可以点个赞

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

成平时努力学习的习惯。所以:贵在坚持!

上面分享的字节跳动公司2020年的面试真题解析大全,笔者还把一线互联网企业主流面试技术要点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

就先写到这,码字不易,写的很片面不好之处敬请指出,如果觉得有参考价值的朋友也可以关注一下我

①「Android面试真题解析大全」PDF完整高清版+②「Android面试知识体系」学习思维导图压缩包阅读下载,最后觉得有帮助、有需要的朋友可以点个赞

[外链图片转存中…(img-j6NdSfim-1715133766423)]

[外链图片转存中…(img-HTynI53z-1715133766424)]

[外链图片转存中…(img-I5dOQhgY-1715133766424)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值