Android仿微信通讯录滑动快速定位功能
先给大家展示下效果图:
实现代码如下:
下面简单说下实现原理。
代码如下 | 复制代码 |
publicclassIndexBarextendsLinearLayoutimplementsView.OnTouchListener { privatestaticfinalString[] INDEXES =newString[]{"#","A","B","C","D","E","F","G","H", "I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}; privatestaticfinalintTOUCHED_BACKGROUND_COLOR =0x40000000; privateOnIndexChangedListener mListener; publicvoidsetOnIndexChangedListener(OnIndexChangedListener listener) { mListener = listener; } publicIndexBar(Context context) { this(context,null); } publicIndexBar(Context context, AttributeSet attrs) { this(context, attrs,0); } publicIndexBar(Context context, AttributeSet attrs,intdefStyleAttr) { super(context, attrs, defStyleAttr); init(attrs); } privatevoidinit(AttributeSet attrs) { TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.IndexBar); floatindexTextSize = ta.getDimension(R.styleable.IndexBar_indexTextSize, Utils.sp2px(getContext(),12)); intindexTextColor = ta.getColor(R.styleable.IndexBar_indexTextColor,0xFF616161); ta.recycle(); setOrientation(VERTICAL); setOnTouchListener(this); for(String index : INDEXES) { TextView text =newTextView(getContext()); text.setText(index); text.setTextSize(TypedValue.COMPLEX_UNIT_PX, indexTextSize); text.setTextColor(indexTextColor); text.setGravity(Gravity.CENTER); LinearLayout.LayoutParams params =newLinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,0,1); text.setLayoutParams(params); addView(text); } } @Override publicbooleanonTouch(View v, MotionEvent event) { switch(event.getAction()) { caseMotionEvent.ACTION_DOWN: setBackgroundColor(TOUCHED_BACKGROUND_COLOR); handle(v, event); returntrue; caseMotionEvent.ACTION_MOVE: handle(v, event); returntrue; caseMotionEvent.ACTION_UP: setBackgroundColor(Color.TRANSPARENT); handle(v, event); returntrue; } returnsuper.onTouchEvent(event); } privatevoidhandle(View v, MotionEvent event) { inty = (int) event.getY(); intheight = v.getHeight(); intposition = INDEXES.length * y / height; if(position<0) { position =0; }elseif(position >= INDEXES.length) { position = INDEXES.length -1; } String index = INDEXES[position]; booleanshowIndicator = event.getAction() != MotionEvent.ACTION_UP; if(mListener !=null) { mListener.onIndexChanged(index, showIndicator); } } publicinterfaceOnIndexChangedListener { voidonIndexChanged(String index,booleanshowIndicator); } } |
使用
代码如下 | 复制代码 |
publicclassCompanyActivityextendsBaseActivityimplementsIndexBar.OnIndexChangedListener { @Bind(R.id.lv_company) ListView lvCompany; @Bind(R.id.ib_indicator) IndexBar ibIndicator; @Bind(R.id.tv_indicator) TextView tvIndicator; privateList @Override protectedvoidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_company); // ... } @Override publicvoidonIndexChanged(String index,booleanshowIndicator) { intposition = -1; for(CompanyEntity company : mCompanyList) { if(TextUtils.equals(company.getName(), index)) { position = mCompanyList.indexOf(company); break; } } if(position != -1) { lvCompany.setSelection(position); } tvIndicator.setText(index); tvIndicator.setVisibility(showIndicator ? View.VISIBLE : View.GONE); } } |
继承自LinearLayout,添加了26个字母索引TextView,当手指滑动时通知Activity更新界面。
核心是OnTouchListener,手指滑动的时候根据当前Y坐标计算出手指所在的索引位置,要注意临界值。
本文介绍了如何正确理解和使用Activity的4种启动模式的教程,非常实用,有兴趣的同学快来看看吧关于Activity启动模式的文章已经很多,但有的文章写得过于简单,有的则过于注重细节,本文想取一个折中,只关注最重要和最常用的概念,原理和使用方法,便于读者正确应用。
Activity的启动模式有4种,分别是standard.singleTop. SingleTask. singleInstance,可以在AndroidMainifest.xml文件中指定每一个Activity的启动模式。一个Android应用一般都会有多个Activity,系统会通过任务栈来管理这些Activity,栈是一种后进先出的集合,当前的Activity就在栈顶,按返回键,栈顶Activity就会退出。Activity启动模式不同,系统通过任务栈管理Activity的方式也会不同,以下将分别介绍。
1 Standard模式
Standard模式是Android的默认启动模式,你不在配置文件中做任何设置,那么这个Activity就是standard模式,这种模式下,Activity可以有多个实例,每次启动Activity,无论任务栈中是否已经有这个Activity的实例,系统都会创建一个新的Activity实例,以下是实验验证。
新建一个FirstActivity,用一个Button去启动它本身:
发现每次都会启动一个新的FristActivity, Log信息如下
什么时候用standard模式呢?standartd模式是activity的默认模式,大部分情况下,都应该使用这种模式,也就是在配置文件中什么都不用做,当确实有特殊需求时,再考虑其他模式。
2 SingleTop模式
SingleTop模式和standard模式非常相似,主要区别就是当一个singleTop模式的Activity已经位于任务栈的栈顶,再去启动它时,不会再创建新的实例,如果不位于栈顶,就会创建新的实例,现在把配置文件中FirstActivity的启动模式改为SingleTop,我们的应用只有一个Activity,FirstActivity自然处于任务栈的栈顶。
当应用第一次启动后,我们再按Button去启动新的FirstActivity,发现Log信息中不再打印onCreate函数,说明不再创建新的FirstActivity实例。
这里有一个新的问题,对于每次启动Activity,我们该如何分别处理。答案就是onNewIntent()函数,虽然系统不会调用onCreat(),但会调用onNewIntent,我们可以在这个函数做相应的处理。
当一个Activity已经在栈顶,但依然有可能启动它,而你又不想产生新的Activity实例,此时就可以用singleTop模式。例如,一个搜索Activity,可以输入搜索内容,也可以产生搜索结果,此时就可以用singleTop模式,不会用户每次搜索都会产生一个实例。
3 SingleTask模式
SingleTask模式的Activity在同一个Task内只有一个实例,如果Activity已经位于栈顶,系统不会创建新的Activity实例,和singleTop模式一样。但Activity已经存在但不位于栈顶时,系统就会把该Activity移到栈顶,并把它上面的activity出栈。修改上面的程序,新建一个SecondActivity,将FirstActivity设置为singleTask启动模式,并让它启动SecondActivity,再让SecondActivity来启动FirstActivity。
Log信息如下
当SecondActivity启动FirstActivity时,并不会调用FirstActivity的onCreate函数,但会调用onNewIntent函数,同时会调用SecondActivity的onDestroy函数,SecondActivity实例被销毁。
singleTask模式和前面两种模式的最大区别就是singleTask模式是任务内单例的,所以我们是否设定Activity为singleTask模式,就是看我们activity是否需要单例,例如你的某个Activity
里面有一个列表,如果有多个实例,有可能导致用户看到的列表不一致,有的Activity需要经常启动,如果每次都创建实例,会导致占用资源过多,这些情况都可以使用singleTask模式,但启动singleTask模式的Activity会导致任务栈内它上面的Activity被销毁,有可能会影响用户体验,使用时要注意。
4 SingleInstance模式
singleInstance模式也是单例的,但和singleTask不同,singleTask只是任务栈内单例,系统里是可以有多个singleTask Activity实例的,而singleInstance Activity在整个系统里只有一个实例,启动一singleInstanceActivity时,系统会创建一个新的任务栈,并且这个任务栈只有他一个Activity。
SingleInstance模式并不常用,如果我们把一个Activity设置为singleInstance模式,你会发现它启动时会慢一些,切换效果不好,影响用户体验。它往往用于多个应用之间,例如一个电视launcher里的Activity,通过遥控器某个键在任何情况可以启动,这个Activity就可以设置为singleInstance模式,当在某应用中按键启动这个Activity,处理完后按返回键,就会回到之前启动它的应用,不影响用户体验。
以上分析了Activity的4种启动模式,将Activity设置为哪种启动模式并没有标准答案,有时候,你可能发现将某个Activity设置为一种启动模式或者另一种启动模式,并没有明显区别,而具体的评判标准就是看哪种模式更满足应用功能,更有利于用户体验。
本文介绍了Android自定义View仿IOS圆盘时间选择器,非常实用,有兴趣的同学可以看看通过自定义view实现仿iOS实现滑动两端的点选择时间的效果
效果图
自定义的view代码
代码如下 | 复制代码 |
publicclassRing_Slide2extendsView { privatestaticfinaldoubleRADIAN =180/ Math.PI; privateintmax_progress;// 设置最大进度 privateintcur_progress;//设置锚点1当前进度 privateintcur_progress2;//设置锚点2进度 privateintbottom_color;//设置底色 privateintcircle_color;//设置圆的颜色(锚点) privateintslide_color;//设置滑动过的颜色 privatefloatring_width;//圆环的宽度 privatedoublecur_Angle;//当前锚点1旋转角度 privatedoublecur_Angle2;//当前锚点2的旋转角度 privatefloatring_Radius;//圆环的半径 privatefinalint[] arrColorCircle =newint[]{0xFFFFde37,0xFFFFa400}; privateintmain_width;//圆的宽度 privatefloatmWheelCurX, mWheelCurY;//圆的位置 privatefloatmWheelCurX2, mWheelCurY2;//圆2的位置 privatePaint circle_Paint;//圆环的画笔 privatePaint select_Paint;//选中的画笔 privatePaint dot1;//圆点1 privatePaint dot2;//圆点2 privateContext context; privateOnSeekBarChangeListener changeListener,changeListener2; publicRing_Slide2(Context context) { this(context,null); } publicRing_Slide2(Context context, AttributeSet attrs) { this(context, attrs,0); } publicRing_Slide2(Context context, AttributeSet attrs,intdefStyleAttr) { super(context, attrs, defStyleAttr); this.context=context; initAttrs(attrs,defStyleAttr); initPadding(); //初始化画笔 initPaints(); } //初始化属性 privatevoidinitAttrs(AttributeSet attrs,intdefStyle){ TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.Cricle_slide, defStyle,0); max_progress=typedArray.getInt(R.styleable.Cricle_slide_max_progress,720); cur_progress=typedArray.getInt(R.styleable.Cricle_slide_cur_progress,420); cur_progress2=typedArray.getInt(R.styleable.Cricle_slide_cur_progress2,540); if(cur_progress > max_progress) cur_progress = max_progress; if(cur_progress2 > max_progress) cur_progress2 = max_progress; Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.select_sun_bg2); main_width= bitmap.getWidth(); ring_width=typedArray.getFloat(R.styleable.Cricle_slide_Ring_Width,main_width); bottom_color=typedArray.getColor(R.styleable.Cricle_slide_bottom_color,getColor(R.color.select_main_bg_color)); circle_color=typedArray.getColor(R.styleable.Cricle_slide_circle_color,getColor(R.color.duration)); slide_color=typedArray.getColor(R.styleable.Cricle_slide_slide_color,getColor(R.color.time)); typedArray.recycle(); } //初始化边距 privatevoidinitPadding(){ intpaddingLeft = getPaddingLeft(); intpaddingTop = getPaddingTop(); intpaddingRight = getPaddingRight(); intpaddingBottom = getPaddingBottom(); intpaddingStart =0, paddingEnd =0; if(Build.VERSION.SDK_INT >=17) { paddingStart = getPaddingStart(); paddingEnd = getPaddingEnd(); } intmaxPadding = Math.max(paddingLeft, Math.max(paddingTop, Math.max(paddingRight, Math.max(paddingBottom, Math.max(paddingStart, paddingEnd))))); setPadding(maxPadding, maxPadding, maxPadding, maxPadding); } privatevoidinitPaints(){ /* 圆环的画笔 */ circle_Paint=new Paint(Paint.ANTI_ALIAS_FLAG); circle_Paint.setAntiAlias(true); circle_Paint.setColor(bottom_color); circle_Paint.setStyle(Paint.Style.STROKE); circle_Paint.setStrokeWidth(ring_width); /* 选中区域的画笔 */ select_Paint=new Paint(Paint.ANTI_ALIAS_FLAG); select_Paint.setShader(new SweepGradient(0, 0, arrColorCircle, null)); /*select_Paint.setColor(circle_color);*/ select_Paint.setAntiAlias(true); select_Paint.setStyle(Paint.Style.STROKE); select_Paint.setStrokeWidth(ring_width); // 画锚点 dot1 = new Paint(Paint.ANTI_ALIAS_FLAG); dot1.setColor(circle_color); dot1.setAntiAlias(true); dot1.setStyle(Paint.Style.FILL); // 画锚点2 dot2 = new Paint(Paint.ANTI_ALIAS_FLAG); dot2.setColor(slide_color); dot2.setAntiAlias(true); dot2.setStyle(Paint.Style.FILL); } //获取宽度 private float getDimen(int dimenId) { return getResources().getDimension(dimenId); } //获取颜色 @TargetApi(Build.VERSION_CODES.M) private int getColor(int colorId) { final int version = Build.VERSION.SDK_INT; if (version >= 23) { return getContext().getColor(colorId); } else { return ContextCompat.getColor(getContext(), colorId); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.setalarm_colock_bg); int height = bitmap.getHeight()+main_width*2; int width = bitmap.getWidth()+main_width*2; int min = Math.min(height, width); setMeasuredDimension(min,min); initposition(); } private void initposition(){ //转换为360度 cur_Angle=(double) cur_progress / max_progress*360.0; cur_Angle2=(double)cur_progress2 / max_progress*360.0; //计算初始化旋转的角度 double cos = -Math.cos(Math.toRadians(cur_Angle)); double cos2 = -Math.cos(Math.toRadians(cur_Angle2)); //根据旋转的角度来确定位置 MakeCurPosition(cos); MakeCurPosition2(cos2); //确定圆环的半径 ring_Radius=(getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - ring_width) / 2; } private void MakeCurPosition(double cos){ //根据旋转的角度来确定圆的位置 //确定x点的坐标 mWheelCurX = calcXLocationInWheel(cur_Angle, cos); //确定y点的坐标 mWheelCurY=calcYLocationInWheel(cos); } private void MakeCurPosition2(double cos2){ //根据旋转的角度来确定圆的位置 //确定x点的坐标 mWheelCurX2 = calcXLocationInWheel(cur_Angle2, cos2); //确定y点的坐标 mWheelCurY2=calcYLocationInWheel(cos2); } //确定x点的坐标 private float calcXLocationInWheel(double angle,double cos){ if (angle < 180) { return (float) (getMeasuredWidth() / 2 + Math.sqrt(1 - cos * cos) * ring_Radius); //Math.sqrt正平分根 9-3 } else { return (float) (getMeasuredWidth() / 2 - Math.sqrt(1 - cos * cos) * ring_Radius); } } //确定y点的坐标 private float calcYLocationInWheel(double cos) { return getMeasuredWidth() / 2 + ring_Radius * (float) cos; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float left = getPaddingLeft() + ring_width / 2; float top = getPaddingTop() + ring_width / 2; float right = canvas.getWidth() - getPaddingRight() - ring_width / 2; float bottom = canvas.getHeight() - getPaddingBottom() - ring_width / 2; float centerX = (left + right) / 2; float centerY = (top + bottom) / 2; float wheelRadius = (canvas.getWidth() - getPaddingLeft() - getPaddingRight()) / 2 - ring_width / 2; canvas.drawCircle(centerX, centerY, wheelRadius, circle_Paint); //画选中区域 // canvas.drawArc(new RectF(left, top, right, bottom), (float) (Math.PI * RADIAN + Math.acos(cur_Angle) * RADIAN), (float) (Math.abs(cur_Angle-cur_Angle2)), false, select_Paint); Log.i("TAG","第一个的角度="+cur_Angle); Log.i("TAG","第一个的角度2="+cur_Angle2); float begin=0; //圆弧的起点位置 float stop=0; if(cur_Angle>180 && cur_Angle>cur_Angle2 ){ //180 -- 360 begin=(float) (-Math.abs(cur_Angle-360)-90); stop=(float) Math.abs(Math.abs(cur_Angle-360)+cur_Angle2); Log.i("TAG","begin="+begin); Log.i("TAG","stop="+stop); }else if(cur_Angle>cur_Angle2){ begin=(float) cur_Angle-90; stop=(float)(360-(cur_Angle-cur_Angle2)); }else { begin=(float) cur_Angle-90; stop=(float) Math.abs(cur_Angle-cur_Angle2); } canvas.drawArc(new RectF(left, top, right, bottom), begin,stop, false, select_Paint); //画锚点 画圆 canvas.drawCircle(mWheelCurX, mWheelCurY, ring_width/2, dot1); //画锚点 画圆 canvas.drawCircle(mWheelCurX2, mWheelCurY2, ring_width/2, dot2); Log.i("TAG","锚点1Y"+mWheelCurY+"锚点1X"+mWheelCurX); Log.i("TAG","锚点2Y"+mWheelCurY2+"锚点1X"+mWheelCurX2); } @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); int flag=0; //判断是否触控到两个点中的其中某个点 if(isMovedot2(x,y)){ flag=2; }else if(isMovedot1(x,y)){ flag=1; } /* if(isMovedot1(x,y)){ flag=1; }else if(isMovedot2(x,y)){ flag=2; }*/ if(event.getAction()==MotionEvent.ACTION_MOVE || isMovedot1(x,y) ==true|| isMovedot2(x,y)==true){ Log.i("TAG","进入X="+x+"进入Y="+y); //通过触摸点算出cos角度值 floatcos = calculateCos(x, y); // 通过反三角函数获得角度值 doubleangle;//获取滑动的角度 if(x < getWidth() /2) {// 滑动超过180度 angle = Math.PI * RADIAN + Math.acos(cos) * RADIAN;//通过计算得到滑动的角度值 }else{// 没有超过180度 angle = Math.PI * RADIAN - Math.acos(cos) * RADIAN;//PI 周长比直径 返回弧角度的余弦值 } if(flag==1){ cur_Angle=angle; cur_progress=getSelectedValue(cur_Angle); MakeCurPosition(cos); if(changeListener !=null) { changeListener.onChanged(this, cur_progress); } }elseif(flag==2){ cur_Angle2=angle; cur_progress2=getSelectedValue(cur_Angle2); MakeCurPosition2(cos); if(changeListener2 !=null) { changeListener2.onChanged(this, cur_progress2); } } invalidate(); returntrue; }else{ returnsuper.onTouchEvent(event); } } privatebooleanisMovedot1(floatx,floaty){ floatdot1x = Math.abs(mWheelCurX - x); floatdot1y = Math.abs(mWheelCurY - y); if(dot1x<30&& dot1y<30){ returntrue; }else{ returnfalse; } } privatebooleanisMovedot2(floatx,floaty){ floatdot1x = Math.abs(mWheelCurX2 - x); floatdot1y = Math.abs(mWheelCurY2 - y); if(dot1x<30&& dot1y<30){ returntrue; }else{ returnfalse; } } //拿到切斜角的cos值 privatefloatcalculateCos(floatx,floaty){ floatwidth = x - getWidth() /2; floatheight = y - getHeight() /2; floatslope = (float) Math.sqrt(width * width + height * height); returnheight / slope; } privateintgetSelectedValue(doublemCurAngle) {//角度转进度 returnMath.round(max_progress * ((float) mCurAngle /360));//四舍五入 } publicvoidsetOnSeekBarChangeListener(OnSeekBarChangeListener listener) { changeListener = listener; } publicvoidsetOnSeekBarChangeListener2(OnSeekBarChangeListener listener) { changeListener2 = listener; } publicvoidinitRadian(intpro1,intpro2){ this.cur_progress=pro1; this.cur_progress2=pro2; invalidate(); } publicinterfaceOnSeekBarChangeListener { voidonChanged(Ring_Slide2 seekbar,intcurValue); } } |
自定义stayle样式,在values下新建sttrs.xml文件
代码如下 | 复制代码 |
//设置最大进度
//设置当前进度
//设置当前进度
//设置底色
//设置圆的颜色
//设置滑动的颜色
//圆环的宽度 (dimension是代表尺寸值)
|
这篇文章主要介绍了Android编程之ActionBar Tabs用法,结合实例形式分析了ActionBar Tabs的功能及Tab切换不同的Fragment的相关实现技巧,需要的朋友可以参考下
这里主要实现用Tab切换不同的Fragment,点击View显示or隐藏ActionBar,把ActionBar 设为透明,使界面更加友好,详细代码见资源里的ActionBarTabs。
ActionBar Tab主要用于Fragment之间的切换,其必须要设置ActionBar.TabListener,详细代码如下
ActionBarActivity.Java:
代码如下 | 复制代码 |
importandroid.app.ActionBar; importandroid.app.Activity; importandroid.app.FragmentTransaction; importandroid.app.ActionBar.Tab; importandroid.os.Bundle; importandroid.os.CountDownTimer; importandroid.view.MotionEvent; importandroid.view.Window; publicclassActionBarActivityextendsActivity { /** Called when the activity is first created. */ @Override publicvoidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //使ActionBar变得透明 requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); setContentView(R.layout.main); finalActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // remove the activity title to make space for tabs actionBar.setDisplayShowTitleEnabled(false); AFragment aFragment =newAFragment(); actionBar.addTab(actionBar.newTab().setText("Tab-A") .setTabListener(newListenerA(aFragment))); BFragment bFragment =newBFragment(); actionBar.addTab(actionBar.newTab().setText("Tab-B") .setTabListener(newListenerB(bFragment))); } //点击显示or隐藏ActionBar publicbooleanonTouchEvent(MotionEvent event){ ActionBar bar = getActionBar(); switch(event.getAction()){ caseMotionEvent.ACTION_UP: if(bar.isShowing()) bar.hide(); elsebar.show(); break; default: break; } returntrue; } privateclassListenerAimplementsActionBar.TabListener { privateAFragment mFragment; // Called to create an instance of the listener when adding a new tab publicListenerA(AFragment fragment) { mFragment = fragment; } publicvoidonTabSelected(Tab tab, FragmentTransaction ft) { ft.add(R.id.fragment, mFragment,null); } publicvoidonTabUnselected(Tab tab, FragmentTransaction ft) { ft.remove(mFragment); } publicvoidonTabReselected(Tab tab, FragmentTransaction ft) { // do nothing } } } privateclassListenerBimplementsActionBar.TabListener { privateBFragment mFragment; // Called to create an instance of the listener when adding a new tab publicListenerB(BFragment fragment) { mFragment = fragment; } publicvoidonTabSelected(Tab tab, FragmentTransaction ft) { ft.add(R.id.fragment, mFragment,null); } publicvoidonTabUnselected(Tab tab, FragmentTransaction ft) { ft.remove(mFragment); } publicvoidonTabReselected(Tab tab, FragmentTransaction ft) { // do nothing } } } } |
其中涉及到两个Fragment,在前面Fragment的笔记中讲过,这里就不再赘述。类AFragment实现如下,BFragment实现与这类似:
代码如下 | 复制代码 |
publicclassAFragmentextendsFragment { publicView onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { returninflater.inflate(R.layout.alayout, container,false); } } |
相关文章
- 下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
Android开发中findViewById()函数用法与简化
findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20- 如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
- 夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
- 为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
- 这篇文章主要为大家详细介绍了python实现学生通讯录管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-25
- 如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
- 深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
- 下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
- java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
- TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
android.os.BinderProxy cannot be cast to com解决办法
本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20- 下面我们来看一篇关于Android 开发之布局细节对比:RTL模式 ,希望这篇文章对各位同学会带来帮助,具体的细节如下介绍。 前言 讲真,好久没写博客了,2016都过了一半了,赶紧...2016-10-02
- 这篇文章主要介绍了Android 实现钉钉自动打卡功能的步骤,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下...2021-03-15
- 首先如果要在程序中使用sdcard进行存储,我们必须要在AndroidManifset.xml文件进行下面的权限设置: 在AndroidManifest.xml中加入访问SDCard的权限如下: <!--...2016-09-20
- 下面来给各位简单的介绍一下关于Android开发之PhoneGap打包及错误解决办法,希望碰到此类问题的同学可进入参考一下哦。 在我安装、配置好PhoneGap项目的所有依赖...2016-09-20
用Intel HAXM给Android模拟器Emulator加速
Android 模拟器 Emulator 速度真心不给力,, 现在我们来介绍使用 Intel HAXM 技术为 Android 模拟器加速,使模拟器运行度与真机比肩。 周末试玩了一下在Eclipse中使...2016-09-20- 在安卓开发时我碰到一个问题就是需要实现全屏,但又需要我们来判断出用户是使用了全屏或非全屏了,下面我分别找了两段代码,大家可参考。 先来看一个android屏幕全屏实...2016-09-20
Android开发中布局中的onClick简单完成多控件时的监听的利与弊
本文章来为各位介绍一篇关于Android开发中布局中的onClick简单完成多控件时的监听的利与弊的例子,希望这个例子能够帮助到各位朋友. 首先在一个控件加上这么一句:and...2016-09-20Ubuntu 系统下安装Android开发环境 Android Studio 1.0 步骤
Android Studio 是一个Android开发环境,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工具用于开发和调试,可以在Linux,Mac OS X,Window...2016-09-20