动手实现自己的Crouton

动手实现自己的Crouton
给个图没图说个jb
这里写图片描述
自己菜逼一个,想找个开源的代码看,没有一个是我能看懂的,干!看见Crouton的源码比较少,尽管代码写的比较好,
可扩展性比较好,但是用不到,我就需要一个显示的功能就可以了。所以仿照它的实现了一个Crouton.
Crouton 和DialogPlus开源的控件的原理都是在Activity上添加一个view,在给这个view设置动画效果,和监听事件。
自己定义一个控件CustomView
在调用Activity addContentView 将view显示在Acitvity上
activity.addContentView(CustoView, params);
设置一个动画效果,弹出CustomView,然后删除CustomView调用CustomView.getParentView.removeView(Crouton)设置一个消失的动画。
这样一个最简单的弹出消失的toast完成了。
你还需要考虑到一点,就是你同时弹出多个toast的情况,Crouton处理的方式,用一个队列存储CroutonView。然后按照先进先出的顺序去显示toast
不bibi了。下面介绍详细的实现方式。
我分析源码喜欢从它调用方式着实,或者查看某个类再几处调用了。一步一步分析。
当然现在分析的不是Crouton,而是GacToast,复制粘贴是我的特长,因为我是菜逼,只能抄和模仿。
调用GacToast 弹出提示框只需要调用下面这一句
GacToast.makeText(this,content,GacToast.ERROR).show();

这里面有两个函数,所以看一下makeText函数,还有一个show函数。
先分析makeText方法:
public static GacToast makeText(Activity activity, CharSequence text, int style) {
return new GacToast(activity, text, style);
}
调用了new GacToast():蛋疼,现在的东西,就是调来调去好麻烦啊,
private GacToast(Activity activity,CharSequence text,int style){
this.activity = activity;
this.viewGroup = null;
this.text = text;
if(style == INFO){
color = holoBlueLight;
}else if(style == ERROR){
color = holoRedLight;
}else{
color = holoGreenLight;
}
}
这个构造函数就是一些给成员变量赋值的作用,并没有实际的感兴趣的东西。
Acitvity 保存当前toast依赖的acitvity
Text 显示的内容
Style 根据不同的类型给toast设置不同的背景颜色。
viewGroup 应该是toast的根布局,其实我自己也不知道,往下看,看不懂的就是猜。
makeText函数就到此结束了。看来主要的东西还是在show方法里面。
下面看一下show方法:
public void show() {
Log.e(“gac”, “show method”);
GacManager.getInstance().add(this);

我擦嘞!就一句话,感觉有些失望。现在又多了两个方法,和一个类:
GacManager getInstance add
先看看getInstance搞什么鬼!
static synchronized GacManager getInstance() {
if (null == INSTANCE) {
INSTANCE = new GacManager();
}

return INSTANCE;
}
好高端的东西,一个单例模式。我tmd到现在都搞不懂单例模式的异步什么同步,不想去思考为什么。费脑子。因为没有尝试过单例模式出错。出了错就知道了。我相信我有一天会栽在单例模式手上的。
看看GacManager初始化干了什么,
private GacManager() {
queue = new LinkedBlockingQueue();
}
一个队列存储GacToast的队列。前面提过,一个activity显示多个toast的时候,采用队列。
至于这个队列LinkedBlockingQueue 链式阻塞队列,我自己都不知道是干嘛的,懒得百度。要不我菜逼呢,不懂也不想懂。用到的时候再看吧。
太累了。反正就是初始化了一个存储toast的队列。
getInstance基本就到头了,下面看看add方法
void add(GacToast crouton) {
queue.add(crouton);
Log.e(“gac”,”add queue”);
//displayCrouton();
displaytost();
}
Add方法嘛!顾名思义就是添加一个东西。把toast添加到队列里去。下面调用了一个displaytoast,好直接,马上就要显示toast了,看看这个方法
到底怎么显示的。跟着代码走不信找不到源头。
private void displaytost(){
首先检查队列是否为空,为空就return,队列没个东西显示个毛啊!!
if (queue.isEmpty()) {
return;
}

Queue.peek取出队列头部的一个元素,仅仅是取出来,不删除的。
GacToast toast = queue.peek();
下面语句判断toast里面的activity,刚才初始化的时候就给activity赋值了,怎么可能为空呢?扯淡呢?
当然了万一为空了,就从队列中去掉这个toast
if (null == toast.getActivity()) {
queue.poll();
}
Log.e(“gac”, “ADD_CROUTON_TO_VIEW”);
Toast isShowing 方法根据ViewGroup 和activity是否为空来返回值 所以第一次调用的时候返回fasle 因为viewgroup为null
if(!toast.isShowing()){
sendMessage(toast, Messages.ADD_CROUTON_TO_VIEW);
}else{
Log.e(“gac”, “DISPLAY_CROUTON”);
sendMessageDelayed(toast, Messages.DISPLAY_CROUTON, calculateCroutonDuration(toast));

我擦看见了两个sendmessage方法,你想到了什么,当然是线程 和handler了。我还没介绍GacManager是什么东西。
GacManager extends Handler
也就是GacManager 通过发送不同的消息,再调用自己内部的handlemessage方法处理不同的结果

private void sendMessage(GacToast toast, final int messageId) {
final Message message = obtainMessage(messageId);
message.obj = toast;
sendMessage(message);
}
看见了 sendMessage 把toast 和一个messageId发过去。

sendMessage(toast, Messages.ADD_CROUTON_TO_VIEW);
sendMessageDelayed(toast, Messages.DISPLAY_CROUTON, calculateCroutonDuration(toast));
光从displaytoast方法里面,我们就发现了两个MessageId 一个AddCrouton_TO_View 和DSIPLAY_CROUTON
这个都是Crouton里的变量,我名字懒得改了,要不别人不知道我直接抄的Crouton.
从这两个MessageID 我们发现一个是添加toastview到acitvity中去,另一个是显示toast的。我瞎猜的别问我为什么。看到这个名字就瞎猜。
我们看一下handlemessage怎么搞的。

public void handleMessage(Message message) {
final GacToast toast = (GacToast) message.obj;
if (null == toast) {
return;
}
switch (message.what) {

case Messages.ADD_CROUTON_TO_VIEW: {
  addToastToView(toast);
  break;

}
case Messages.REMOVE_CROUTON:
  removeCrouton(toast);
  break;
case Messages.DISPLAY_CROUTON:
  displaytost();
  break;

}

}
这个方法里的displytoast方法我们已分析了viewgroup==null 是发送ADD_CROUTON_TO_VIEW消息
Viewgroup !=null 发送REMOVE_CROUTON消息。其实本质上就是执行两个方法。
当然了第一次执行的时候我们发送的是ADD消息:执行addToastView方法。所以我们首先分析这个方法。
private void addToastToView(final GacToast toast){
if (toast.isShowing()) {
return;
}
//toast.getView方法主要是初始toast的view 并且设置背景颜色 文本内容,以及动画效果
final View view = toast.getView();
如果view的父布局为空就给他设置一个布局
if (null == view.getParent()) {
ViewGroup.LayoutParams params = view.getLayoutParams();
if (null == params) {
params =
new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
// display Crouton in ViewGroup if it has been supplied

  Activity activity = toast.getActivity();
  if (null == activity || activity.isFinishing()) {
    return;
  }

//如果你用的actionbar请将我注释的方法打开,这个计算actionbar的高度来设置toast的margintop值
//我用的toolbar actionbar 设置为false 所以我手动给他设置了一个值,我是一个菜逼,我从来不关注代码的扩展性
再牛逼的代码我也能给他改废了。
//toolbar 不需要设置ActionBar 直接指定ToolBar的高度
// handleTranslucentActionBar((ViewGroup.MarginLayoutParams) params, activity);
//handleActionBarOverlay((ViewGroup.MarginLayoutParams) params, activity);
((ViewGroup.MarginLayoutParams) params).topMargin = ActivityUtils.dip2px(toast.getActivity(),80.0f);
这个方法就是我上面提到的将toastview添加到acitvity中去
activity.addContentView(view, params);

}
你认为addToastToView方法到此 结束了你就错了,下面还有一大堆,
view.requestLayout(); // This is needed so the animation can use the measured with/height
关于这个ViewTreeObserver是干嘛的真心不知道,有知道的跟我说一下,我很好奇,因为自定义view经常见到,
ViewTreeObserver observer = view.getViewTreeObserver();
if (null != observer) {
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
@TargetApi(16)
public void onGlobalLayout() {

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
给toast的view设置动画并且启动动画,你可以联想一下toast弹出来的场景了。
view.startAnimation(toast.getInAnimation());
下面这个方法别问我我也不知道,有知道的跟我说一下我很好奇。
announceForAccessibilityCompat(toast.getActivity(), toast.getText());
Toast显示出来后 发送一个remove消息。下面执行remove方法了。
//延迟显示的时间发送删除消息
sendMessageDelayed(toast, Messages.REMOVE_CROUTON,
TIME_DURATION + toast.getInAnimation().getDuration());
}
});
}

protected void removeCrouton(GacToast crouton) {
// If the crouton hasn’t been displayed yet a Crouton.hide() will fail to hide
// it since the DISPLAY message might still be in the queue. Remove all messages
// for this crouton.
将这个toast里面的message删除 貌似是handler里的机制
removeAllMessagesForCrouton(crouton);
下面这两句获取toast的view 和它的父布局。
View croutonView = crouton.getView();
ViewGroup croutonParentView = (ViewGroup) croutonView.getParent();

if (null != croutonParentView) {
//croutonView.setAlpha(0f);
Toast的父布局不为空的话,就开始设置退出的动画,
croutonView.startAnimation(crouton.getOutAnimation());

// Remove the Crouton from the queue.
GacToast removed = queue.poll();

// Remove the crouton from the view's parent.
croutonParentView.removeView(croutonView);这一条语句就是我说的从activity中删除这个toast
if (null != removed) {
  removed.detachActivity();
  removed.detachViewGroup();

}

// Send a message to display the next crouton but delay it by the out
// animation duration to make sure it finishes
//延迟当前toast退出的动作时间继续发送显示时间 

退出之后就要发生显示信息,做人不能太自私万一队列里还有toast 你不发送这个其它toast怎么显示呢。 还有你发送显示toast的消息时候的,
你需要等当前toast退出去吧。
sendMessageDelayed(crouton, Messages.DISPLAY_CROUTON, crouton.getOutAnimation().getDuration());
}
}

不想写了00:41了。大致流程就是这样,剩下的自己看代码吧。程序员坑程序员,程序员勾搭程序员。我越来感觉这个真是个真理了。
源码地址:看评论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要在Chromebook上安装Linux,您需要先启用Chromebook上的开发者模式。然后,您可以通过Crouton或Chromebrew等工具来安装Linux。安装Linux后,您可以使用Linux应用程序和命令行工具来扩展Chromebook的功能。但请注意,安装Linux可能会影响Chromebook的安全性和稳定性,因此请谨慎操作。 ### 回答2: Chromebook是一种基于Chrome OS的操作系统的笔记本电脑。虽然Chrome OS可以运行许多应用程序,但有些用户需要更广泛的功能,例如使用Linux的命令行和软件。因此,可以在Chromebook上安装Linux以满足这些需求。 首先,要安装Linux,您需要启用Chromebook上的“开发者模式”。要进入开发者模式,首先,请备份您的所有文件并确保Chromebook已连接到电源。然后,按住Esc + F3(Chromebook上的切换功能键)+ 电源按钮,然后释放所有这些键。Chromebook将进入恢复模式。 在恢复模式下,您需要按Ctrl + D,然后按Enter键。您将会收到一条警告,提示您确信要进入开发者模式。按Enter再次确认。Chromebook将自行重启并进入开发者模式。 现在您有了开发者模式,需要打开Chromebook上的“Linux(Beta)”功能。前往Chromebook的设置并选择“设备”>“Linux Beta”,随后按照提示启用它。系统将自动下载并安装Linux虚拟机容器。 与此同时,建议您下载和安装一个名为“Crouton”的Linux发行版,它与Chrome OS安装在同一个虚拟机容器中,并为您提供享有Linux游戏和软件的命令行界面。该软件也能帮助您在Chromebook上快速安装Linux发行版。 最后,为了使用Linux,您需要打开终端并输入以下命令:sudo startgnome 或 sudo startxfce4。这将启动您安装的GNOME或Xfce桌面环境。现在,您可以使用Linux命令行和应用程序,您可以在Chromebook上进行更广泛的任务! 总之,将Linux安装到Chromebook上是一个相对简单的过程,需要您注意一些关键步骤。一旦您完成了所有步骤,您将能够在Chromebook上使用Linux的命令行和应用程序,满足您更广泛的需求。 ### 回答3: 随着Chromebook在市场上的快速普及,越来越多的用户想要在Chromebook上使用Linux。Chromebook本身是一种基于Google Chrome浏览器的操作系统,但是安装Linux可以为用户提供更多功能和灵活性。 首先需要说明的是,Chromebook是基于Google Chrome OS的,这意味着它并不是一个传统意义上的计算机。Chromebook的本质是一款浏览器,因此它并不支持像Windows或Mac OS那样的原生程序安装。这就是为什么在Chromebook中安装Linux会比在其他设备上更加复杂的原因。 但是,Chromebook作为一种基于Linux内核的操作系统,是可以使用Linux的。Google为Chromebook提供了一个称为“开发人员模式”的选项,用户可以在这个模式下安装和运行Linux应用程序。以下是步骤: 步骤一:打开“开发人员模式” - 这个选项可以通过按下“ESC + 刷新 + 电源”来打开,这样您就可以进入Chromebook的开发人员模式。 步骤二:下载Crouton - Crouton是一个用于在Chromebook上安装Linux的软件。 步骤三:启动Crouton - 打开“终端”并输入以下命令: sudo sh ~/Downloads/crouton -t [desktop environment] [desktop environment]将是您想要安装的桌面环境。例如,如果您想要安装Ubuntu,这将是“xfce”或“unity”之一。 步骤四:等待安装完成 - 安装会需要一些时间。安装完成后,您将可以通过在Chromebook的开发人员模式下切换到Linux环境。 总的来说,Chromebook在安装Linux方面略有些复杂,但对于那些想要更多功能和灵活性的用户来说,这是一个值得尝试的方法。如果遵循正确的步骤,安装Linux将为Chromebook带来更多功用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值