【lua教程】自制气泡拖动条
require "import"import "android.app.*"
import "android.os.*"
import "android.widget.*"
import "android.view.*"
activity.setTitle('自绘制气泡拖动条')
activity.setTheme(android.R.style.Theme_DeviceDefault_Light)--设置md主题
activity.setContentView(loadlayout({
ScrollView;
layout_height="fill";
layout_width="fill";
{
LinearLayout;
layout_width="fill";
gravity="top";
layout_height="fill";
orientation="vertical";
{
TextView;
layout_width="fill";
padding="15dp";
id="t1";
};
{
View;
layout_width="fill";
layout_height="35dp";
id="animseekBar";
};
{
TextView;
layout_width="fill";
padding="15dp";
id="t2";
};
};
}
))
import "android.graphics.*"
import "android.graphics.Paint$Style"
import "android.view.animation.*"
import "android.animation.ObjectAnimator"
import "android.animation.PropertyValuesHolder"
dip2px=function(dpValue)
local scale = activity.getResources().getDisplayMetrics().density;
return dpValue * scale + 0.5
end
sp2px=function(spValues)
local fontScale = activity.getResources().getDisplayMetrics().scaledDensity;
return spValues * fontScale+ 0.5
end
getStatusBarHeight=function()
_,statusBarHeight2=xpcall(function()
local clazz=Class.forName("com.android.internal.R$dimen")
local object = clazz.newInstance();
local height = Integer.parseInt(tostring(clazz.getField("status_bar_height").get(object)))
return this.getResources().getDimensionPixelSize(height);
end,
function(a)
_,statusBarHeight1=pcall(function()
local resourceId = this.getResources().getIdentifier("status_bar_height", "dimen", "android");
if resourceId > 0
return this.getResources().getDimensionPixelSize(resourceId);
end
end,
function(e)
end,nil)
end,
nil)
if type(statusBarHeight2):lower()=="number"
return statusBarHeight2
elseif type(statusBarHeight1):lower()=="number"
return statusBarHeight1
else
return 0
end
end
BgColor=0xFFBDBDBD--背景色
TopColor=0xFF9C27B0--进度条颜色
TopHandleColor=0xFF9C27B0--滑块颜色
BubblesColor=0xffffffff--气泡字体颜色
BgHeight=dip2px(3)--背景高度
TopHeight=dip2px(4)--进度条高度
TopHandle=dip2px(8)--滑块半径
Max=100--最大值
Dragprogress=0--当前进度
CanvasMargin=dip2px(48)--边距
bubblesTextSize=sp2px(12)--气泡内文字大小
Seekbarids=animseekBar
import "android.content.Context"
mWindowManager = activity.getSystemService(Context.WINDOW_SERVICE);
IndicatorWindow=function(getH,getW)
local mLayoutParams = WindowManager.LayoutParams();
mLayoutParams.gravity = Gravity.START | Gravity.BOTTOM;
mLayoutParams.width =getW;
mLayoutParams.height = getH;
mLayoutParams.format = PixelFormat.TRANSLUCENT;
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
--MIUI禁止了开发者使用TYPE_TOAST,Android 7.1.1 对TYPE_TOAST的使用更严格
if Build.MANUFACTURER:lower()~="xiaomi" or Build.VERSION.SDK_INT >= 25
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION;
else
mLayoutParams.type = WindowManager.LayoutParams.TYPE_TOAST;
end
return mLayoutParams
end
ShowBubbles=function(ids)
local mBubbleView=
{
LinearLayout;
layout_width="fill";
layout_height="fill";
id="Mcft_Main",
{
View,
id=ids,
layout_width="54dp";
layout_height="55dp";
Visibility=View.GONE,
}
}
mWindowManager.addView(loadlayout(mBubbleView), IndicatorWindow(0,0) );
end
PaintBubbles=function(progess)
newPaint=Paint()
newPaint.setTextSize(bubblesTextSize)
TextMin=newPaint.measureText(tostring(progess))
Indicator=sp2px(24)
BubblesSize=bubblesTextSize+sp2px(3)
local Paintd=LuaDrawable(function(canvas,paint)
local cW=canvas.Width
local cH=canvas.Height
paint.setAntiAlias(true)
paint.setStyle(Style.FILL);
paint.setFakeBoldText(false)
paint.setTextSize(bubblesTextSize)
paint.setColor(TopHandleColor)
local path =Path()
path.moveTo(Indicator/2,(cH/1.75))
path.lineTo(cW-(Indicator/2),cH/1.75)
path.lineTo(cW/2,cH)
path.close()
canvas.drawPath(path, paint)
canvas.drawCircle(cW/2,cH/2,BubblesSize, paint);
paint.setColor(BubblesColor)
canvas.drawText(tostring(progess),(cW/2)-(TextMin/2),(cH/2)+(bubblesTextSize/2.5),paint)
end)
return {draw=Paintd,Circlesize=(BubblesSize*2)+Indicator}
end
locationUpdate=function(views,getX,getY,progess)
local outRect1 = Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1);
local WidowHeight=outRect1.height()
-Seekbarids.getParent().getHeight()
local clazz=Class.forName("com.android.internal.R$dimen")
local object = clazz.newInstance();
local height = Integer.parseInt(tostring(clazz.getField("status_bar_height").get(object)))
local status_bar_height = this.getResources().getDimensionPixelSize(height);
local BuDraw=PaintBubbles(progess)
views.setBackground(BuDraw.draw)
views.setX(getX+((CanvasMargin/2)-(views.getWidth()/2)))
views.setY((getY+status_bar_height)-(views.getHeight()/2))
--views.setImageDrawable(BuDraw.draw)
local newParams=IndicatorWindow(outRect1.height(),Seekbarids.getParent().getWidth())
mWindowManager.updateViewLayout(views.getParent(), newParams);
end
LogoutBubble=function(view)
mWindowManager.removeViewImmediate(view.getParent());
end
PropertyS=function(a,b,view,isType)
local Attribute_definition = PropertyValuesHolder.ofFloat("method",{ a,b})
local mValueAnimator = ObjectAnimator.ofPropertyValuesHolder({Attribute_definition})
.setStartDelay(0)
.setInterpolator(AnticipateOvershootInterpolator())
.setDuration(500)
mValueAnimator.addUpdateListener({
onAnimationUpdate=function(animation)
local Animationaprogress=animation.getAnimatedValue()
if isType
view.setVisibility(View.VISIBLE)
end
view.setAlpha(Animationaprogress)
view.setPivotY(view.getHeight()*1.4)
.setPivotX(view.getWidth()/2)
.setScaleX(Animationaprogress)
.setScaleY(Animationaprogress)
--.setRotationX(-90+(Animationaprogress*90))
AnimFolatN=Animationaprogress
SeekbarAmin.invalidateSelf()
end,
});
mValueAnimator.addListener({
onAnimationEnd=function()
if not isType
view.setVisibility(View.GONE)
LogoutBubble(view)
end
end
}).start()
end
--mBubbleView.setVisibility(GONE); --防闪烁
--mLayoutParams.x = (mBubbleCenterRawX + 0.5f);
--mWindowManager.updateViewLayout(mBubbleView, mLayoutParams);
getWidthPercentage=function(w,max,proges)
local WidthDivision=(w/max)*proges
return {TowX=WidthDivision,Proges=proges}
end
AnimFolatN=0
SeekbarAmin=LuaDrawable(function(canvas,piant,d)
canvasWidth=canvas.getWidth()-CanvasMargin
canvasHeight=canvas.getHeight()
canvas.translate(CanvasMargin/2,0)
piant.setStrokeCap(Paint.Cap.ROUND)
piant.setAntiAlias(true)
--画背景进度条
piant.setColor(BgColor);
piant.setStrokeWidth(BgHeight);
canvas.drawLines({0,canvasHeight/2,canvasWidth,canvasHeight/2},piant)
--画顶部进度条
piant.setColor(TopColor);
piant.setStrokeWidth(TopHeight+((TopHeight/4)*AnimFolatN));
canvas.drawLines({0,canvasHeight/2,getWidthPercentage(canvasWidth,Max,Dragprogress).TowX,canvasHeight/2},piant)
--画滑块
piant.setColor(0x23000000);
canvas.drawCircle(getWidthPercentage(canvasWidth,Max,Dragprogress).TowX,canvasHeight/2,((TopHandle*1.7)*AnimFolatN), piant);
piant.setColor(TopHandleColor);
canvas.drawCircle(getWidthPercentage(canvasWidth,Max,Dragprogress).TowX,canvasHeight/2,TopHandle-((TopHandle)*AnimFolatN), piant);
end)
Seekbarids.background=SeekbarAmin
getPView=function(a)
a=a.getParent()
while a~=nil and not tostring(a):find("ScrollView")
a=a.getParent()
end
return a==nil and 0 or a.getScrollY()
end
Seekbarids.onTouch=function(v,event)
local Maction=event.getAction()
if Maction==MotionEvent.ACTION_DOWN
if event.getX()>CanvasMargin/2 and event.getX()<v.getWidth()-CanvasMargin/2
and event.getY()>(v.getHeight()/2)-TopHandle and event.getY()<(v.getHeight()/2)+TopHandle
WithinRange=true
ShowBubbles("bubbles")
PropertyS(0,1,bubbles,true)
v.getParent().requestDisallowInterceptTouchEvent(true);
else
WithinRange=false
end
elseif Maction==MotionEvent.ACTION_MOVE
if WithinRange
v.getParent().requestDisallowInterceptTouchEvent(true);
local getXTo=event.getX()
local ranger=(event.getX()-CanvasMargin/2)/(v.getWidth()-CanvasMargin)
--计算百分比
Dragprogress=tointeger((ranger<=0 and 0 or (ranger>=1 and 1 or ranger))*Max)
locationUpdate(bubbles,getWidthPercentage(Seekbarids.getWidth()-CanvasMargin,Max,Dragprogress).TowX
,Seekbarids.getY()-getPView(v),Dragprogress)
SeekbarAmin.invalidateSelf()
end
elseif Maction==MotionEvent.ACTION_UP
v.getParent().requestDisallowInterceptTouchEvent(false);
pcall(function()
if bubbles and WithinRange
PropertyS(1,0,bubbles,false)
end
end)
end
return true;
end
t1.text=[[
Android一词的本义指“机器人”,同时也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统、中间件、用户界面和应用软件组成。
]]
t2.text=[[
2003年10月,Andy Rubin等人创建Android公司,并组建Android团队。
2005年8月17日,Google低调收购了成立仅22个月的高科技企业Android及其团队。安迪鲁宾成为Google公司工程部副总裁,继续负责Android项目。
2007年11月5日,谷歌公司正式向外界展示了这款名为Android的操作系统,并且在这天谷歌宣布建立一个全球性的联盟组织,该组织由34家手机制造商、软件开发商、电信运营商以及芯片制造商共同组成,并与84家硬件制造商、软件开发商及电信营运商组成开放手持设备联盟(Open Handset Alliance)来共同研发改良Android系统,这一联盟将支持谷歌发布的手机操作系统以及应用软件,Google以Apache免费开源许可证的授权方式,发布了Android的源代码。
2008年,在GoogleI/O大会上,谷歌提出了AndroidHAL架构图,在同年8月18号,Android获得了美国联邦通信委员会(FCC)的批准,在2008年9月,谷歌正式发布了Android 1.0系统,这也是Android系统最早的版本。
2009年4月,谷歌正式推出了Android 1.5这款手机,从Android 1.5版本开始,谷歌开始将Android的版本以甜品的名字命名,Android 1.5命名为Cupcake(纸杯蛋糕)。该系统与Android 1.0相比有了很大的改进。
2009年9月,谷歌发布了Android 1.6的正式版,并且推出了搭载Android 1.6正式版的手机HTC Hero(G3),凭借着出色的外观设计以及全新的Android 1.6操作系统,HTC Hero(G3)成为当时全球最受欢迎的手机。Android 1.6也有一个有趣的甜品名称,它被称为Donut(甜甜圈)。
2010年2月,Linux内核开发者Greg Kroah-Hartman将Android的驱动程序从Linux内核“状态树”(“staging tree”)上除去,从此,Android与Linux开发主流将分道扬镳。在同年5月份,谷歌正式发布了Android 2.2操作系统。谷歌将Android 2.2操作系统命名为Froyo,翻译完名为冻酸奶。
2010年10月,谷歌宣布Android系统达到了第一个里程碑,即电子市场上获得官方数字认证的Android应用数量已经达到了10万个,Android系统的应用增长非常迅速。在2010年12月,谷歌正式发布了Android 2.3操作系统Gingerbread (姜饼)。
2011年1月,谷歌称每日的Android设备新用户数量达到了30万部,到2011年7月,这个数字增长到55万部,而Android系统设备的用户总数达到了1.35亿,Android系统已经成为智能手机领域占有量最高的系统。
2011年8月2日,Android手机已占据全球智能机市场48%的份额,并在亚太地区市场占据统治地位,终结了Symbian(塞班系统)的霸主地位,跃居全球第一。
2011年9月,Android系统的应用数目已经达到了48万,而在智能手机市场,Android系统的占有率已经达到了43%。继续在排在移动操作系统首位。谷歌将会发布全新的Android 4.0操作系统,这款系统被谷歌命名为Ice Cream Sandwich(冰激凌三明治)。
2012年1月6日,谷歌Android Market已有10万开发者推出超过40万活跃的应用,大多数的应用程序为免费。Android Market应用程序商店目录在新年首周周末突破40万基准,距离突破30万应用仅4个月。在2011年早些时候,Android Market从20万增加到30万应用也花了四个月。
2013年11月1日,Android4.4正式发布,从具体功能上讲,Android4.4提供了各种实用小功能,新的Android系统更智能,添加更多的Emoji表情图案,UI的改进也更现代,如全新的HelloiOS7半透明效果。
2015年,网络安全公司Zimperium研究人员警告,安卓(Android)存在“致命”安全漏洞,黑客发送一封彩信便能在用户毫不知情的情况下完全控制手机。
2018年10月,谷歌表示,将于2018年12月6日停止Android系统中的Nearby Notifications(附近通知)服务,因为Android用户收到太多的附近商家推销信息的垃圾邮件。
2020年3月,谷歌的Android安全公告中提到,新更新已经提供了CVE-2020-0069补丁来解决针对联发科芯片的一个严重安全漏洞。
]]
来源:代码手册 Robin
页:
[1]