Android自定义View精品(RollWeekView-炫酷的星期日期选择控件)

本文主要是介绍Android自定义View精品(RollWeekView-炫酷的星期日期选择控件),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

版权声明:本文为openXu原创文章【openXu的博客】,未经博主允许不得以任何形式转载

目录:

文章目录

    • 1、分析
    • 2、定义控件布局
    • 3、定义CustomWeekView
    • 4、重写onMeasure
    • 5、点击后执行动画
    • 7、重置预备控件

  最近收到一个自定义控件的需求,需要做一个日期选择控件,实现图如下:
     这里写图片描述

  一次展示一个星期的5天,中间放大的为当前选中的;如果点击了其中一个日期,比如星期五,那么整体向左滑动,并将星期五慢慢放大,星期三慢慢缩小,星期六和星期天就展示出来了;如果继续点击星期六,那么照样是整体向左滑动一个单位,星期日右边就需要塞进一个星期一。就是一个无限循环的过程,中间选中的需要展示当天的日期。

1、分析

  最开始,我想到在LinearLayout中依次排开7个子控件(星期几),当点击之后,把所有的子控件通过动画移动相应的偏移量,但是,如果移动后就会出现空位的情况(周一的左边和周日的右边没有了),所以这种方式可是可以,但是要解决无限循环空位的情况。
  于是就想到能不能多添加几个子控件作为空位替补?这个方法肯定能实现,但是究竟需要多少个替补呢?这些替补应该放在什么位置呢?
  当前展示的5个子控件中,如果点击最左边或者最右边,这样的偏移量是最大的,需要便宜两个子控件单位,所以左边和右边最多个需要2个替补就行了,算起来也不多,一共才9个(当前展示5个,左边隐藏替补2个,右边隐藏替补2个)。在点击之前,先将替补位置设置好,当点击之后,所有子控件执行偏移动画(不可能出现空位,最多偏移2位),动画结束之后,再重新为隐藏的4个替补分配位置并绑定数据,绑定什么数据那就看当前中间显示的是星期几了。

分析图如下:
这里写图片描述

  但是新的问题又来了,动画执行完毕之后,怎么判断哪些子控件是当前正在显示的呢(中间五个)?由于正在显示的子控件的位置是可以确定的,因为要重写onMeasure(),在onMeasure()方法中可以得到单个子控件的宽度(item_width=getMeasureWidth()/5),动画结束之后,遍历这些子控件,如果x==0的那肯定就是当前正在展示的第一个子控件,x==item_width则是第二个…,剩余的4个就不用判断了,直接将两个移动到左边,两个移动到右边,然后重新为这四个替补设置数据。

2、定义控件布局

组合控件的布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"android:gravity="center_vertical"><LinearLayoutandroid:id="@+id/ll_1"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"><LinearLayoutandroid:layout_width="@dimen/week_item_sise"android:layout_height="@dimen/week_item_sise"android:background="@drawable/week_one_bg"android:orientation="vertical"android:gravity="center"><TextViewandroid:id="@+id/tv_1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /><TextViewandroid:id="@+id/tv_date1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_2"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"><LinearLayoutandroid:layout_width="@dimen/week_item_sise"android:layout_height="@dimen/week_item_sise"android:background="@drawable/week_one_bg"android:orientation="vertical"android:gravity="center"><TextViewandroid:id="@+id/tv_2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /><TextViewandroid:id="@+id/tv_date2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_3"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"><LinearLayoutandroid:layout_width="@dimen/week_item_sise"android:layout_height="@dimen/week_item_sise"android:background="@drawable/week_one_bg"android:orientation="vertical"android:gravity="center"><TextViewandroid:id="@+id/tv_3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /><TextViewandroid:id="@+id/tv_date3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_4"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"><LinearLayoutandroid:layout_width="@dimen/week_item_sise"android:layout_height="@dimen/week_item_sise"android:background="@drawable/week_one_bg"android:orientation="vertical"android:gravity="center"><TextViewandroid:id="@+id/tv_4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /><TextViewandroid:id="@+id/tv_date4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_5"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"><LinearLayoutandroid:layout_width="@dimen/week_item_sise"android:layout_height="@dimen/week_item_sise"android:background="@drawable/week_one_bg"android:orientation="vertical"android:gravity="center"><TextViewandroid:id="@+id/tv_5"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /><TextViewandroid:id="@+id/tv_date5"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_6"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"><LinearLayoutandroid:layout_width="@dimen/week_item_sise"android:layout_height="@dimen/week_item_sise"android:background="@drawable/week_one_bg"android:orientation="vertical"android:gravity="center"><TextViewandroid:id="@+id/tv_6"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /><TextViewandroid:id="@+id/tv_date6"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_7"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"><LinearLayoutandroid:layout_width="@dimen/week_item_sise"android:layout_height="@dimen/week_item_sise"android:background="@drawable/week_one_bg"android:orientation="vertical"android:gravity="center"><TextViewandroid:id="@+id/tv_7"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /><TextViewandroid:id="@+id/tv_date7"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_8"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"><LinearLayoutandroid:layout_width="@dimen/week_item_sise"android:layout_height="@dimen/week_item_sise"android:background="@drawable/week_one_bg"android:orientation="vertical"android:gravity="center"><TextViewandroid:id="@+id/tv_8"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /><TextViewandroid:id="@+id/tv_date8"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_9"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"><LinearLayoutandroid:layout_width="@dimen/week_item_sise"android:layout_height="@dimen/week_item_sise"android:background="@drawable/week_one_bg"android:orientation="vertical"android:gravity="center"><TextViewandroid:id="@+id/tv_9"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /><TextViewandroid:id="@+id/tv_date9"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="周" /></LinearLayout></LinearLayout>
</LinearLayout>

3、定义CustomWeekView

  布局写完后,接下来应该找一个容器接纳他们,这个容器就是我们定义的CustomWeekView,让其继承LinearLayout,然后重写构造方法,并初始化子控件;此处自定义属性就不再赘述,之前的所有自定义控件案例中都讲解过,如果不熟悉请参考 Android自定义View(二、深入解析自定义属性):

public class CustomWeekView extends LinearLayout{public CustomWeekView(Context context) {this(context, null);
}public CustomWeekView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CustomWeekView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}private void init(Context context, AttributeSet attrs) {LayoutInflater.from(context).inflate(R.layout.custom_week_layout, this, true);ll_1 = (LinearLayout) findViewById(R.id.ll_1);ll_2 = (LinearLayout) findViewById(R.id.ll_2);...tv_1 = (TextView) findViewById(R.id.tv_1);tv_2 = (TextView) findViewById(R.id.tv_2);...tv_date1 = (TextView) findViewById(R.id.tv_date1);tv_date2 = (TextView) findViewById(R.id.tv_date2);...if (attrs != null) {TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LimitScroller);limit = 5;background = ta.getColor(R.styleable.LimitScroller_android_background, Color.TRANSPARENT);textSize = ta.getDimension(R.styleable.LimitScroller_android_textSize, 15f);final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;textSize = textSize / fontScale + 0.5f;dateTextSize = ta.getInteger(R.styleable.LimitScroller_dateTextSize, 12);textColor = ta.getColor(R.styleable.LimitScroller_android_textColor, Color.BLACK);dateTextColor = ta.getColor(R.styleable.LimitScroller_dateTextColor, Color.RED);durationTime = ta.getInt(R.styleable.LimitScroller_durationTime, 1000);scaleSize = ta.getFloat(R.styleable.LimitScroller_scaleSize, 0);ta.recycle();  //注意回收}}
}

4、重写onMeasure

  由于本控件宽度是填充父窗体,高度是包裹内容,这里不需要我们手动写代码测量,直接调用super.onMeasure()好了。(onMeasure()详解请移步:Android自定义View(三、深入解析控件测量onMeasure))。但是我们需要在测量完毕后,计算子控件的宽度并初次安置每个子控件的位置,这个宽度就是后面移动的单位,也作为位置判断的依据。由于onMeasure()方法会被调用多次(后面设置位置、显示隐藏等等操作都会导致onMeasure()触发),所以需要判断一下如果ITEM_WIDTH<=0才需要计算;然后还要为子控件设置初始日期:

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//        Log.w(TAG, "测量完成,宽度*高度="+getMeasuredWidth()+"*"+getMeasuredHeight());if(ITEM_WIDTH<=0) {ITEM_WIDTH = getMeasuredWidth()/limit;
//            Log.w(TAG, "每小项尺寸:"+ITEM_WIDTH+"*"+getMeasuredHeight());measureInit();}if(ll_2.getX()>0 && !isFirstSeted) {//设置今天的日期在中间animalFinish = false;Calendar cal = Calendar.getInstance();int todayNum = cal.get(Calendar.DAY_OF_WEEK)-1;Log.d(TAG, "今天是星期"+WEEK_STR[todayNum]);setCenter(getEnumByNum(todayNum));animalFinish = true;isFirstSeted = true;}}/**根据屏幕的宽度和显示的个数,设置item的宽度*/
private void measureInit(){LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)ll_1.getLayoutParams();lp.width = ITEM_WIDTH;ll_1.setLayoutParams(lp);lp = (LinearLayout.LayoutParams)ll_2.getLayoutParams();lp.width = ITEM_WIDTH;ll_2.setLayoutParams(lp);lp = (LinearLayout.LayoutParams)ll_3.getLayoutParams();lp.width = ITEM_WIDTH;ll_3.setLayoutParams(lp);lp = (LinearLayout.LayoutParams)ll_4.getLayoutParams();lp.width = ITEM_WIDTH;ll_4.setLayoutParams(lp);lp = (LinearLayout.LayoutParams)ll_5.getLayoutParams();lp.width = ITEM_WIDTH;ll_5.setLayoutParams(lp);lp = (LinearLayout.LayoutParams)ll_6.getLayoutParams();lp.width = ITEM_WIDTH;ll_6.setLayoutParams(lp);lp = (LinearLayout.LayoutParams)ll_7.getLayoutParams();lp.width = ITEM_WIDTH;ll_7.setLayoutParams(lp);lp = (LinearLayout.LayoutParams)ll_8.getLayoutParams();lp.width = ITEM_WIDTH;ll_8.setLayoutParams(lp);lp = (LinearLayout.LayoutParams)ll_9.getLayoutParams();lp.width = ITEM_WIDTH;ll_9.setLayoutParams(lp);
}

5、点击后执行动画

  上面的步骤完成之后,基本上已经完成的控件的初始设置,接下来就是点击子控件后执行动画了。这里一共需要执行两套动画,一套是缩放动画、一套是移动动画。添加点击事件的代码就不贴出来了,下面是执行动画的方法:

private void startAnimation(final WEEKDAY centerWitch, final LinearLayout llClickView) {if(centerWitch==centerNow)return;animalFinish = false;LinearLayout innerLL = (LinearLayout)ll3.getChildAt(0);TextView tvDate = (TextView)innerLL.getChildAt(1);tvDate.setVisibility(View.GONE);innerLL = (LinearLayout)llClickView.getChildAt(0);tvDate = (TextView)innerLL.getChildAt(1);tvDate.setVisibility(View.VISIBLE);//根据当前中间位置显示的 和 被点击的日期,获取需要偏移的增量int offset = getXOffset(centerWitch);Log.d(TAG, "当前中间为"+centerNow+",点击的是"+centerWitch+ "  偏移量:"+offset);//当前中间位置的需要缩放到原尺寸
//        Log.v(TAG, "中间item缩放量scaleX="+ll3.getChildAt(0).getScaleX()+" scaleY="+ll3.getChildAt(0).getScaleY());ObjectAnimator anim100 = ObjectAnimator.ofFloat(ll3.getChildAt(0), "scaleX", ll3.getChildAt(0).getScaleX(), 1.0f);ObjectAnimator anim101 = ObjectAnimator.ofFloat(ll3.getChildAt(0), "scaleY", ll3.getChildAt(0).getScaleY(), 1.0f);//被点击的需要放大ObjectAnimator anim102 = ObjectAnimator.ofFloat(llClickView.getChildAt(0), "scaleX", 1, scaleSize);ObjectAnimator anim103 = ObjectAnimator.ofFloat(llClickView.getChildAt(0), "scaleY", 1, scaleSize);//透明度动画ObjectAnimator anim104 = ObjectAnimator.ofFloat(llClickView.getChildAt(0), "scaleY", 1, scaleSize);//位移动画ObjectAnimator anim1 = ObjectAnimator.ofFloat(ll_1, "X", ll_1.getX(), ll_1.getX() + offset);ObjectAnimator anim2 = ObjectAnimator.ofFloat(ll_2, "X", ll_2.getX(), ll_2.getX() + offset);ObjectAnimator anim3 = ObjectAnimator.ofFloat(ll_3, "X", ll_3.getX(), ll_3.getX() + offset);ObjectAnimator anim4 = ObjectAnimator.ofFloat(ll_4, "X", ll_4.getX(), ll_4.getX() + offset);ObjectAnimator anim5 = ObjectAnimator.ofFloat(ll_5, "X", ll_5.getX(), ll_5.getX() + offset);ObjectAnimator anim6 = ObjectAnimator.ofFloat(ll_6, "X", ll_6.getX(), ll_6.getX() + offset);ObjectAnimator anim7 = ObjectAnimator.ofFloat(ll_7, "X", ll_7.getX(), ll_7.getX() + offset);ObjectAnimator anim8 = ObjectAnimator.ofFloat(ll_8, "X", ll_8.getX(), ll_8.getX() + offset);ObjectAnimator anim9 = ObjectAnimator.ofFloat(ll_9, "X", ll_9.getX(), ll_9.getX() + offset);AnimatorSet animSet = new AnimatorSet();animSet.setDuration(durationTime);animSet.playTogether(anim100, anim101, anim102, anim103, anim1, anim2, anim3, anim4, anim5, anim6, anim7, anim8, anim9);animSet.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {Log.w(TAG, "动画结束后位置:"+ll_1.getX()+" "+ll_2.getX()+" "+ll_3.getX()+" "+ll_4.getX()+" "+ll_5.getX()+" "+ll_6.getX()+" "+ll_7.getX()+" "+ll_8.getX()+" "+ll_9.getX());setCenter(centerWitch);animalFinish = true;}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});animSet.start();}

7、重置预备控件

  动画执行完毕之后,要做两个操作。第一个就是将当前不在显示范围的4个子控件左右各放2个,第二步就是为预备控件绑定新的星期日期。下面的方法是根据各个子控件的坐标来判断是隐藏还是展示,然后为隐藏的控件重新安排位置;然后绑定数据:

/*这些引用代表当前正在显示的5个条目 和 四个预备条目,*由于ll_x系列条目是不断移动的,所以此处需要根据ll_x的位置重新为llx赋值* 其中ll1-ll5为当前正在显示的条目, ll6、ll7为右边隐藏的预备条目, ll8、ll9为左边的隐藏预备条目*/private LinearLayout ll1, ll2, ll3, ll4, ll5, ll6, ll7, ll8, ll9;/**1、找到正在展示的五个item,并将预备item复位*/private void setCenter(WEEKDAY weekDay){//记录当前显示在中间的星期XcenterNow = weekDay;//1、找到当前显示的5个条目的位置List<LinearLayout> list = new ArrayList<>(llList);for(int i = 0; i<5; i++){for(int j = 0; j<list.size(); j++){LinearLayout ll = list.get(j);if(ll.getX()==ITEM_WIDTH*i){list.remove(ll);      //找到之后就remove可以减少后面遍历的次数
//                    Log.d(TAG, "找到"+i+"了"+ll);switch (i) {case 0:ll1 = ll;break;case 1:ll2 = ll;break;case 2:ll3 = ll;//当前中间位置item放大ll3.getChildAt(0).setScaleX(scaleSize);ll3.getChildAt(0).setScaleY(scaleSize);break;case 3:ll4 = ll;break;case 4:ll5 = ll;break;}}}}Log.i(TAG, "找完后还剩"+list.size()+"  总:"+llList.size());//2、剩余的四个作为预备,归位,左边隐藏两个,右边隐藏两个for(int i = 0; i<list.size(); i++){LinearLayout ll = list.get(i);switch (i){case 0:   //左1ll.setX(-ITEM_WIDTH*2);ll8=ll;break;case 1:   //左2ll.setX(-ITEM_WIDTH*1);ll9=ll;break;case 2:   //右1ll.setX(ITEM_WIDTH*5);ll6=ll;break;case 3:   //右2ll.setX(ITEM_WIDTH*6);ll7=ll;break;}}//绑定数据reBoundDataByCenter(weekDay);}/**2、重新绑定数据*/private void reBoundDataByCenter(WEEKDAY weekDay){if(weekDay == WEEKDAY.wk1){/*星期1在中间,依次为4、5、6、7、1、2、3、4、5*/setLLText(ll8, 4, false);setLLText(ll9, 5, false);setLLText(ll1, 6, false);setLLText(ll2, 7, false);setLLText(ll3, 1, true);setLLText(ll4, 2, false);setLLText(ll5, 3, false);setLLText(ll6, 4, false);setLLText(ll7, 5, false);}else if(weekDay == WEEKDAY.wk2){/*星期2在中间,依次为5、6、7、1、2、3、4、5、6*/setLLText(ll8, 5, false);setLLText(ll9, 6, false);setLLText(ll1, 7, false);setLLText(ll2, 1, false);setLLText(ll3, 2, true);setLLText(ll4, 3, false);setLLText(ll5, 4, false);setLLText(ll6, 5, false);setLLText(ll7, 6, false);}else if(weekDay == WEEKDAY.wk3){/*星期3在中间,依次为6、7、1、2、3、4、5、6、7*/setLLText(ll8, 6, false);setLLText(ll9, 7, false);setLLText(ll1, 1, false);setLLText(ll2, 2, false);setLLText(ll3, 3, true);setLLText(ll4, 4, false);setLLText(ll5, 5, false);setLLText(ll6, 6, false);setLLText(ll7, 7, false);}else if(weekDay == WEEKDAY.wk4){/*星期4在中间,依次为7、1、2、3、4、5、6、7、1*/setLLText(ll8, 7, false);setLLText(ll9, 1, false);setLLText(ll1, 2, false);setLLText(ll2, 3, false);setLLText(ll3, 4, true);setLLText(ll4, 5, false);setLLText(ll5, 6, false);setLLText(ll6, 7, false);setLLText(ll7, 1, false);}else if(weekDay == WEEKDAY.wk5){/*星期5在中间,依次为1、2、3、4、5、6、7、1、2*/setLLText(ll8, 1, false);setLLText(ll9, 2, false);setLLText(ll1, 3, false);setLLText(ll2, 4, false);setLLText(ll3, 5, true);setLLText(ll4, 6, false);setLLText(ll5, 7, false);setLLText(ll6, 1, false);setLLText(ll7, 2, false);}else if(weekDay == WEEKDAY.wk6){/*星期6在中间,依次为2、3、4、5、6、7、1、2、3*/setLLText(ll8, 2, false);setLLText(ll9, 3, false);setLLText(ll1, 4, false);setLLText(ll2, 5, false);setLLText(ll3, 6, true);setLLText(ll4, 7, false);setLLText(ll5, 1, false);setLLText(ll6, 2, false);setLLText(ll7, 3, false);}else if(weekDay == WEEKDAY.wk7){/*星期7在中间,依次为3、4、5、6、7、1、2、3、4*/setLLText(ll8, 3, false);setLLText(ll9, 4, false);setLLText(ll1, 5, false);setLLText(ll2, 6, false);setLLText(ll3, 7, true);setLLText(ll4, 1, false);setLLText(ll5, 2, false);setLLText(ll6, 3, false);setLLText(ll7, 4, false);}}private void setLLText(LinearLayout ll, int witchDay, boolean showDate){ll.setTag(witchDay);   //便于区分点击事件LinearLayout innerLL = (LinearLayout)ll.getChildAt(0);TextView tv = (TextView)innerLL.getChildAt(0);String text = "星期" + WEEK_STR[witchDay];tv.setText(text);TextView tvDate = (TextView)innerLL.getChildAt(1);text = DATE_STR.get(witchDay);tvDate.setText(text);if(showDate){tvDate.setVisibility(View.VISIBLE);}else{tvDate.setVisibility(View.GONE);}}

  当执行完上面的方法后,控件的状态又回到了初始状态,下次点击又会重复上面的步骤。因为动画执行完后,只有被隐藏的子控件需要重新安排位置,所以,不会出现闪跳的现象。

最终效果图如下:

      这里写图片描述

喜欢请点赞,no爱请勿喷~O(∩_∩)O谢谢

##源码下载:

http://download.csdn.net/detail/u010163442/9698848 CSDN下载平台太流氓

https://github.com/openXu/JueAnimation

这篇关于Android自定义View精品(RollWeekView-炫酷的星期日期选择控件)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/968206

相关文章

WinForms中主要控件的详细使用教程

《WinForms中主要控件的详细使用教程》WinForms(WindowsForms)是Microsoft提供的用于构建Windows桌面应用程序的框架,它提供了丰富的控件集合,可以满足各种UI设计... 目录一、基础控件1. Button (按钮)2. Label (标签)3. TextBox (文本框

Python日期和时间完全指南与实战

《Python日期和时间完全指南与实战》在软件开发领域,‌日期时间处理‌是贯穿系统设计全生命周期的重要基础能力,本文将深入解析Python日期时间的‌七大核心模块‌,通过‌企业级代码案例‌揭示最佳实践... 目录一、背景与核心价值二、核心模块详解与实战2.1 datetime模块四剑客2.2 时区处理黄金法

Java进行日期解析与格式化的实现代码

《Java进行日期解析与格式化的实现代码》使用Java搭配ApacheCommonsLang3和Natty库,可以实现灵活高效的日期解析与格式化,本文将通过相关示例为大家讲讲具体的实践操作,需要的可以... 目录一、背景二、依赖介绍1. Apache Commons Lang32. Natty三、核心实现代

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

exfat和ntfs哪个好? U盘格式化选择NTFS与exFAT的详细区别对比

《exfat和ntfs哪个好?U盘格式化选择NTFS与exFAT的详细区别对比》exFAT和NTFS是两种常见的文件系统,它们各自具有独特的优势和适用场景,以下是关于exFAT和NTFS的详细对比... 无论你是刚入手了内置 SSD 还是便携式移动硬盘或 U 盘,都需要先将它格式化成电脑或设备能够识别的「文

Android 实现一个隐私弹窗功能

《Android实现一个隐私弹窗功能》:本文主要介绍Android实现一个隐私弹窗功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 效果图如下:1. 设置同意、退出、点击用户协议、点击隐私协议的函数参数2. 《用户协议》、《隐私政策》设置成可点击的,且颜色要区分出来res/l

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

Android开发环境配置避坑指南

《Android开发环境配置避坑指南》本文主要介绍了Android开发环境配置过程中遇到的问题及解决方案,包括VPN注意事项、工具版本统一、Gerrit邮箱配置、Git拉取和提交代码、MergevsR... 目录网络环境:VPN 注意事项工具版本统一:android Studio & JDKGerrit的邮