自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android自定義控件:類QQ未讀消息拖拽效果

移動開發(fā) Android
QQ的未讀消息,算是一個比較好玩的效果,趁著最近時間比較多,參考了網(wǎng)上的一些資料之后,本次實現(xiàn)一個仿照QQ未讀消息的拖拽小紅點。

QQ的未讀消息,算是一個比較好玩的效果,趁著最近時間比較多,參考了網(wǎng)上的一些資料之后,本次實現(xiàn)一個仿照QQ未讀消息的拖拽小紅點:

首先我們從最基本的原理開始分析,看一張圖:

 

這個圖該怎么繪制呢?實際上我們這里是先繪制兩個圓,然后將兩個圓的切點通過貝塞爾曲線連接起來就達到這個效果了。至于貝塞爾曲線的概念,這里就不多做解釋了,百度一下就知道了。

 

切點怎么算呢,這里我們稍微復習一些初中的數(shù)學知識??戳诉@個圖之后,求出四個切點應該是輕而易舉了。

 

現(xiàn)在思路已經(jīng)很清晰了,按照我們的思路,開擼。

首先是我們計算切點以及各坐標點的工具類

  1. public class GeometryUtils { 
  2.     /** 
  3.      * As meaning of method name
  4.      * 獲得兩點之間的距離 
  5.      * @param p0 
  6.      * @param p1 
  7.      * @return 
  8.      */ 
  9.     public static float getDistanceBetween2Points(PointF p0, PointF p1) { 
  10.         float distance = (float) Math.sqrt(Math.pow(p0.y - p1.y, 2) + Math.pow(p0.x - p1.x, 2)); 
  11.         return distance; 
  12.     } 
  13.  
  14.     /** 
  15.      * Get middle point between p1 and p2. 
  16.      * 獲得兩點連線的中點 
  17.      * @param p1 
  18.      * @param p2 
  19.      * @return 
  20.      */ 
  21.     public static PointF getMiddlePoint(PointF p1, PointF p2) { 
  22.         return new PointF((p1.x + p2.x) / 2.0f, (p1.y + p2.y) / 2.0f); 
  23.     } 
  24.  
  25.     /** 
  26.      * Get point between p1 and p2 by percent. 
  27.      * 根據(jù)百分比獲取兩點之間的某個點坐標 
  28.      * @param p1 
  29.      * @param p2 
  30.      * @param percent 
  31.      * @return 
  32.      */ 
  33.     public static PointF getPointByPercent(PointF p1, PointF p2, float percent) { 
  34.         return new PointF(evaluateValue(percent, p1.x , p2.x), evaluateValue(percent, p1.y , p2.y)); 
  35.     } 
  36.  
  37.     /** 
  38.      * 根據(jù)分度值,計算從start到end中,fraction位置的值。fraction范圍為0 -> 1 
  39.      * @param fraction 
  40.      * @param start 
  41.      * @param end 
  42.      * @return 
  43.      */ 
  44.     public static float evaluateValue(float fraction, Number start, Number end){ 
  45.         return start.floatValue() + (end.floatValue() - start.floatValue()) * fraction; 
  46.     } 
  47.  
  48.     /** 
  49.      * Get the point of intersection between circle and line. 
  50.      * 獲取 通過指定圓心,斜率為lineK的直線與圓的交點。 
  51.      * 
  52.      * @param pMiddle The circle center point. 
  53.      * @param radius The circle radius. 
  54.      * @param lineK The slope of line which cross the pMiddle. 
  55.      * @return 
  56.      */ 
  57.     public static PointF[] getIntersectionPoints(PointF pMiddle, float radius, Double lineK) { 
  58.         PointF[] points = new PointF[2]; 
  59.  
  60.         float radian, xOffset = 0, yOffset = 0; 
  61.         if(lineK != null){ 
  62.             radian= (float) Math.atan(lineK); 
  63.             xOffset = (float) (Math.sin(radian) * radius); 
  64.             yOffset = (float) (Math.cos(radian) * radius); 
  65.         }else { 
  66.             xOffset = radius; 
  67.             yOffset = 0; 
  68.         } 
  69.         points[0] = new PointF(pMiddle.x + xOffset, pMiddle.y - yOffset); 
  70.         points[1] = new PointF(pMiddle.x - xOffset, pMiddle.y + yOffset); 
  71.  
  72.         return points; 
  73.     } 
  74.  

然后下面看下我們的核心繪制代碼,代碼注釋比較全,此處就不多做解釋了。

  1. /** 
  2.      * 繪制貝塞爾曲線部分以及固定圓 
  3.      * 
  4.      * @param canvas 
  5.      */ 
  6.     private void drawGooPath(Canvas canvas) { 
  7.         Path path = new Path(); 
  8.         //1. 根據(jù)當前兩圓圓心的距離計算出固定圓的半徑 
  9.         float distance = (float) GeometryUtils.getDistanceBetween2Points(mDragCenter, mStickCenter); 
  10.         stickCircleTempRadius = getCurrentRadius(distance); 
  11.  
  12.         //2. 計算出經(jīng)過兩圓圓心連線的垂線的dragLineK(對邊比臨邊)。求出四個交點坐標 
  13.         float xDiff = mStickCenter.x - mDragCenter.x; 
  14.         Double dragLineK = null
  15.         if (xDiff != 0) { 
  16.             dragLineK = (double) ((mStickCenter.y - mDragCenter.y) / xDiff); 
  17.         } 
  18.  
  19.         //分別獲得經(jīng)過兩圓圓心連線的垂線與圓的交點(兩條垂線平行,所以dragLineK相等)。 
  20.         PointF[] dragPoints = GeometryUtils.getIntersectionPoints(mDragCenter, dragCircleRadius, dragLineK); 
  21.         PointF[] stickPoints = GeometryUtils.getIntersectionPoints(mStickCenter, stickCircleTempRadius, dragLineK); 
  22.  
  23.         //3. 以兩圓連線的0.618處作為 貝塞爾曲線 的控制點。(選一個中間點附近的控制點) 
  24.         PointF pointByPercent = GeometryUtils.getPointByPercent(mDragCenter, mStickCenter, 0.618f); 
  25.  
  26.         // 繪制兩圓連接閉合 
  27.         path.moveTo((float) stickPoints[0].x, (float) stickPoints[0].y); 
  28.         path.quadTo((float) pointByPercent.x, (float) pointByPercent.y, 
  29.                 (float) dragPoints[0].x, (float) dragPoints[0].y); 
  30.         path.lineTo((float) dragPoints[1].x, (float) dragPoints[1].y); 
  31.         path.quadTo((float) pointByPercent.x, (float) pointByPercent.y, 
  32.                 (float) stickPoints[1].x, (float) stickPoints[1].y); 
  33.         canvas.drawPath(path, mPaintRed); 
  34.         // 畫固定圓 
  35.         canvas.drawCircle(mStickCenter.x, mStickCenter.y, stickCircleTempRadius, mPaintRed); 
  36.     }  

此時我們已經(jīng)實現(xiàn)了繪制的核心代碼,然后我們加上touch事件的監(jiān)聽,達到動態(tài)的更新dragPoint的中心點位置以及stickPoint半徑的效果。當手抬起的時候,添加一個屬性動畫,達到回彈的效果。

  1. @Override 
  2.     public boolean onTouchEvent(MotionEvent event) { 
  3.         switch (MotionEventCompat.getActionMasked(event)) { 
  4.             case MotionEvent.ACTION_DOWN: { 
  5.                 isOutOfRange = false
  6.                 updateDragPointCenter(event.getRawX(), event.getRawY()); 
  7.                 break; 
  8.             } 
  9.             case MotionEvent.ACTION_MOVE: { 
  10.                 //如果兩圓間距大于***距離mMaxDistance,執(zhí)行拖拽結(jié)束動畫 
  11.                 PointF p0 = new PointF(mDragCenter.x, mDragCenter.y); 
  12.                 PointF p1 = new PointF(mStickCenter.x, mStickCenter.y); 
  13.                 if (GeometryUtils.getDistanceBetween2Points(p0, p1) > mMaxDistance) { 
  14.                     isOutOfRange = true
  15.                     updateDragPointCenter(event.getRawX(), event.getRawY()); 
  16.                     return false
  17.                 } 
  18.                 updateDragPointCenter(event.getRawX(), event.getRawY()); 
  19.                 break; 
  20.             } 
  21.             case MotionEvent.ACTION_UP: { 
  22.                 handleActionUp(); 
  23.                 break; 
  24.             } 
  25.             default: { 
  26.                 isOutOfRange = false
  27.                 break; 
  28.             } 
  29.         } 
  30.         return true
  31.     } 
  32.  
  33.     /** 
  34.      * 手勢抬起動作 
  35.      */ 
  36.     private void handleActionUp() { 
  37.         if (isOutOfRange) { 
  38.             // 當拖動dragPoint范圍已經(jīng)超出mMaxDistance,然后又將dragPoint拖回mResetDistance范圍內(nèi)時 
  39.             if (GeometryUtils.getDistanceBetween2Points(mDragCenter, mStickCenter) < mResetDistance) { 
  40.                 //reset 
  41.                 return
  42.             } 
  43.             // dispappear 
  44.         } else { 
  45.             //手指抬起時,彈回動畫 
  46.             mAnim = ValueAnimator.ofFloat(1.0f); 
  47.             mAnim.setInterpolator(new OvershootInterpolator(5.0f)); 
  48.  
  49.             final PointF startPoint = new PointF(mDragCenter.x, mDragCenter.y); 
  50.             final PointF endPoint = new PointF(mStickCenter.x, mStickCenter.y); 
  51.             mAnim.addUpdateListener(new AnimatorUpdateListener() { 
  52.                 @Override 
  53.                 public void onAnimationUpdate(ValueAnimator animation) { 
  54.                     float fraction = animation.getAnimatedFraction(); 
  55.                     PointF pointByPercent = GeometryUtils.getPointByPercent(startPoint, endPoint, fraction); 
  56.                     updateDragPointCenter((float) pointByPercent.x, (float) pointByPercent.y); 
  57.                 } 
  58.             }); 
  59.             mAnim.addListener(new AnimatorListenerAdapter() { 
  60.                 @Override 
  61.                 public void onAnimationEnd(Animator animation) { 
  62.                     //reset 
  63.                 } 
  64.             }); 
  65.  
  66.             if (GeometryUtils.getDistanceBetween2Points(startPoint, endPoint) < 10) { 
  67.                 mAnim.setDuration(100); 
  68.             } else { 
  69.                 mAnim.setDuration(300); 
  70.             } 
  71.             mAnim.start(); 
  72.         } 
  73.     }  

此時我們拖拽的核心代碼基本都已經(jīng)完成,實際效果如下:

 

現(xiàn)在小紅點的繪制基本告一段落,我們不得不去思考真正的難點。那就是如何將我們前面的這個GooView應用到實際呢?看實際效果我們的小紅點是放在listView里面的,如果是這樣的話,就代表我們的GooView的拖拽范圍是肯定無法超過父控件item的區(qū)域的。

那么我們要如何實現(xiàn)小紅點可以隨便的在整個屏幕拖拽呢?我們這里稍微整理一下思路。

1.先在listView的item布局中先放入一個小紅點。

2.當我們touch到這個小紅點的時候,隱藏這個小紅點,然后根據(jù)我們布局中小紅點的位置初始化一個GooView并且添加到WindowManager中嗎,達到GooView可以全屏拖動的效果。

3.在添加GooView到WindowManager中的時候,記錄初始小紅點stickPoint的位置,然后根據(jù)stickPoint和dragPointde位置是否超出我們的消失界限來判斷接下來的邏輯。

4.根據(jù)GooView的最終狀態(tài),顯示回彈或者消失動畫。

思路有了,那么就上代碼,根據(jù)***步,我們完成listView的item布局。

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.                 android:layout_width="match_parent" 
  4.                 android:layout_height="80dp" 
  5.                 android:minHeight="80dp"
  6.  
  7.     <ImageView 
  8.         android:id="@+id/iv_head" 
  9.         android:layout_width="50dp" 
  10.         android:layout_height="50dp" 
  11.         android:layout_centerVertical="true" 
  12.         android:layout_marginLeft="20dp" 
  13.         android:src="@mipmap/head"/> 
  14.  
  15.     <TextView 
  16.         android:id="@+id/tv_content" 
  17.         android:layout_width="wrap_content" 
  18.         android:layout_height="50dp" 
  19.         android:layout_centerVertical="true" 
  20.         android:gravity="center" 
  21.         android:layout_marginLeft="20dp" 
  22.         android:layout_toRightOf="@+id/iv_head" 
  23.         android:text="content - " 
  24.         android:textSize="25sp"/> 
  25.  
  26.     <LinearLayout 
  27.         android:id="@+id/ll_point" 
  28.         android:layout_width="80dp" 
  29.         android:layout_height="80dp" 
  30.         android:layout_alignParentEnd="true" 
  31.         android:layout_alignParentRight="true" 
  32.         android:layout_alignParentTop="true" 
  33.         android:gravity="center"
  34.  
  35.         <TextView 
  36.             android:id="@+id/point" 
  37.             android:layout_width="wrap_content" 
  38.             android:layout_height="18dp" 
  39.             android:background="@drawable/red_bg" 
  40.             android:gravity="center" 
  41.             android:singleLine="true" 
  42.             android:textColor="@android:color/white" 
  43.             android:textSize="12sp"/> 
  44.     </LinearLayout> 
  45. </RelativeLayout>  

效果如下,要注意的是,對比QQ的真實體驗,小紅點周邊范圍點擊的時候,都是可以直接拖拽小紅點的??紤]到紅點的點擊范圍比較小,所以給紅點增加了一個寬高80dp的父layout,然后我們將touch小紅點事件更改為touch小紅點父layout,這樣只要我們點擊了小紅點的父layout范圍,都會添加GooView到WindowManager中。 

 

接下來第二步,我們完成添加GooView到WindowManager中的代碼。

由于我們的GooView初始添加是從listViewItem中紅點的touch事件開始的,所以我們先完成listView adapter的實現(xiàn)。

  1. public class GooViewAapter extends BaseAdapter { 
  2.     private Context mContext; 
  3.     //記錄已經(jīng)remove的position 
  4.     private HashSet<Integer> mRemoved = new HashSet<Integer>(); 
  5.     private List<String> list = new ArrayList<String>(); 
  6.  
  7.     public GooViewAapter(Context mContext, List<String> list) { 
  8.         super(); 
  9.         this.mContext = mContext; 
  10.         this.list = list; 
  11.     } 
  12.  
  13.     @Override 
  14.     public int getCount() { 
  15.         return list.size(); 
  16.     } 
  17.  
  18.     @Override 
  19.     public Object getItem(int position) { 
  20.         return list.get(position); 
  21.     } 
  22.  
  23.     @Override 
  24.     public long getItemId(int position) { 
  25.         return position; 
  26.     } 
  27.  
  28.     @Override 
  29.     public View getView(final int position, View convertView, ViewGroup parent) { 
  30.         if (convertView == null) { 
  31.             convertView = View.inflate(mContext, R.layout.list_item_goo, null); 
  32.         } 
  33.         ViewHolder holder = ViewHolder.getHolder(convertView); 
  34.         holder.mContent.setText(list.get(position)); 
  35.         //item固定小紅點layout 
  36.         LinearLayout pointLayout = holder.mPointLayout; 
  37.         //item固定小紅點 
  38.         final TextView point = holder.mPoint; 
  39.  
  40.         boolean visiable = !mRemoved.contains(position); 
  41.         pointLayout.setVisibility(visiable ? View.VISIBLE : View.GONE); 
  42.         if (visiable) { 
  43.             point.setText(String.valueOf(position)); 
  44.             pointLayout.setTag(position); 
  45.             GooViewListener mGooListener = new GooViewListener(mContext, pointLayout) { 
  46.                 @Override 
  47.                 public void onDisappear(PointF mDragCenter) { 
  48.                     super.onDisappear(mDragCenter); 
  49.                     mRemoved.add(position); 
  50.                     notifyDataSetChanged(); 
  51.                     Utils.showToast(mContext, "position " + position + " disappear."); 
  52.                 } 
  53.  
  54.                 @Override 
  55.                 public void onReset(boolean isOutOfRange) { 
  56.                     super.onReset(isOutOfRange); 
  57.                     notifyDataSetChanged();//刷新ListView 
  58.                     Utils.showToast(mContext, "position " + position + " reset."); 
  59.                 } 
  60.             }; 
  61.             //在point父布局內(nèi)的觸碰事件都進行監(jiān)聽 
  62.             pointLayout.setOnTouchListener(mGooListener); 
  63.         } 
  64.         return convertView; 
  65.     } 
  66.  
  67.     static class ViewHolder { 
  68.  
  69.         public ImageView mImage; 
  70.         public TextView mPoint; 
  71.         public LinearLayout mPointLayout; 
  72.         public TextView mContent; 
  73.  
  74.         public ViewHolder(View convertView) { 
  75.             mImage = (ImageView) convertView.findViewById(R.id.iv_head); 
  76.             mPoint = (TextView) convertView.findViewById(R.id.point); 
  77.             mPointLayout = (LinearLayout) convertView.findViewById(R.id.ll_point); 
  78.             mContent = (TextView) convertView.findViewById(R.id.tv_content); 
  79.         } 
  80.  
  81.         public static ViewHolder getHolder(View convertView) { 
  82.             ViewHolder holder = (ViewHolder) convertView.getTag(); 
  83.             if (holder == null) { 
  84.                 holder = new ViewHolder(convertView); 
  85.                 convertView.setTag(holder); 
  86.             } 
  87.             return holder; 
  88.         } 
  89.     } 
  90.  

由于listview需要知道GooView的狀態(tài),所以我們在GooView中增加一個接口,用于listView回調(diào)處理后續(xù)的邏輯。

  1. interface OnDisappearListener { 
  2.         /** 
  3.          * GooView Disapper 
  4.          * 
  5.          * @param mDragCenter 
  6.          */ 
  7.         void onDisappear(PointF mDragCenter); 
  8.  
  9.         /** 
  10.          * GooView onReset 
  11.          * 
  12.          * @param isOutOfRange 
  13.          */ 
  14.         void onReset(boolean isOutOfRange); 
  15.       }  

新建一個實現(xiàn)了OnTouchListener以及OnDisappearListener 方法的的類,***將這個實現(xiàn)類設置給item中的紅點Layout。

  1. public class GooViewListener implements OnTouchListener, OnDisappearListener { 
  2.  
  3.     private WindowManager mWm; 
  4.     private WindowManager.LayoutParams mParams; 
  5.     private GooView mGooView; 
  6.     private View pointLayout; 
  7.     private int number; 
  8.     private final Context mContext; 
  9.  
  10.     private Handler mHandler; 
  11.  
  12.     public GooViewListener(Context mContext, View pointLayout) { 
  13.         this.mContext = mContext; 
  14.         this.pointLayout = pointLayout; 
  15.         this.number = (Integer) pointLayout.getTag(); 
  16.  
  17.         mGooView = new GooView(mContext); 
  18.  
  19.         mWm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 
  20.         mParams = new WindowManager.LayoutParams(); 
  21.         mParams.format = PixelFormat.TRANSLUCENT;//使窗口支持透明度 
  22.         mHandler = new Handler(mContext.getMainLooper()); 
  23.     } 
  24.  
  25.     @Override 
  26.     public boolean onTouch(View v, MotionEvent event) { 
  27.         int action = MotionEventCompat.getActionMasked(event); 
  28.         // 當按下時,將自定義View添加到WindowManager中 
  29.         if (action == MotionEvent.ACTION_DOWN) { 
  30.             ViewParent parent = v.getParent(); 
  31.             // 請求其父級View不攔截Touch事件 
  32.             parent.requestDisallowInterceptTouchEvent(true); 
  33.  
  34.             int[] points = new int[2]; 
  35.             //獲取pointLayout在屏幕中的位置(layout的左上角坐標) 
  36.             pointLayout.getLocationInWindow(points); 
  37.             //獲取初始小紅點中心坐標 
  38.             int x = points[0] + pointLayout.getWidth() / 2; 
  39.             int y = points[1] + pointLayout.getHeight() / 2; 
  40.             // 初始化當前點擊的item的信息,數(shù)字及坐標 
  41.             mGooView.setStatusBarHeight(Utils.getStatusBarHeight(v)); 
  42.             mGooView.setNumber(number); 
  43.             mGooView.initCenter(x, y); 
  44.             //設置當前GooView消失監(jiān)聽 
  45.             mGooView.setOnDisappearListener(this); 
  46.             // 添加當前GooView到WindowManager 
  47.             mWm.addView(mGooView, mParams); 
  48.             pointLayout.setVisibility(View.INVISIBLE); 
  49.         } 
  50.         // 將所有touch事件轉(zhuǎn)交給GooView處理 
  51.         mGooView.onTouchEvent(event); 
  52.         return true
  53.     } 
  54.  
  55.     @Override 
  56.     public void onDisappear(PointF mDragCenter) { 
  57.         //disappear 下一步完成 
  58.     } 
  59.  
  60.     @Override 
  61.     public void onReset(boolean isOutOfRange) { 
  62.         // 當dragPoint彈回時,去除該View,等下次ACTION_DOWN的時候再添加 
  63.         if (mWm != null && mGooView.getParent() != null) { 
  64.             mWm.removeView(mGooView); 
  65.         } 
  66.     } 
  67.  

這樣下來,我們基本上完成了大部分功能,現(xiàn)在還差***一步,就是GooView超出范圍消失后的處理,這里我們用一個幀動畫來完成爆炸效果。

  1. public class BubbleLayout extends FrameLayout { 
  2.     Context context; 
  3.  
  4.     public BubbleLayout(Context context) { 
  5.         super(context); 
  6.         this.context = context; 
  7.     } 
  8.  
  9.     private int mCenterX, mCenterY; 
  10.  
  11.     public void setCenter(int x, int y) { 
  12.         mCenterX = x; 
  13.         mCenterY = y; 
  14.         requestLayout(); 
  15.     } 
  16.  
  17.     @Override 
  18.     protected void onLayout(boolean changed, int leftint topint right
  19.                             int bottom) { 
  20.         View child = getChildAt(0); 
  21.         // 設置View到指定位置 
  22.         if (child != null && child.getVisibility() != GONE) { 
  23.             final int width = child.getMeasuredWidth(); 
  24.             final int height = child.getMeasuredHeight(); 
  25.             child.layout((int) (mCenterX - width / 2.0f), (int) (mCenterY - height / 2.0f) 
  26.                     , (int) (mCenterX + width / 2.0f), (int) (mCenterY + height / 2.0f)); 
  27.         } 
  28.     } 
  29.  
  30. @Override 
  31.     public void onDisappear(PointF mDragCenter) { 
  32.         if (mWm != null && mGooView.getParent() != null) { 
  33.             mWm.removeView(mGooView); 
  34.  
  35.             //播放氣泡爆炸動畫 
  36.             ImageView imageView = new ImageView(mContext); 
  37.             imageView.setImageResource(R.drawable.anim_bubble_pop); 
  38.             AnimationDrawable mAnimDrawable = (AnimationDrawable) imageView 
  39.                     .getDrawable(); 
  40.  
  41.             final BubbleLayout bubbleLayout = new BubbleLayout(mContext); 
  42.             bubbleLayout.setCenter((int) mDragCenter.x, (int) mDragCenter.y - Utils.getStatusBarHeight(mGooView)); 
  43.  
  44.             bubbleLayout.addView(imageView, new FrameLayout.LayoutParams( 
  45.                     android.widget.FrameLayout.LayoutParams.WRAP_CONTENT, 
  46.                     android.widget.FrameLayout.LayoutParams.WRAP_CONTENT)); 
  47.  
  48.             mWm.addView(bubbleLayout, mParams); 
  49.  
  50.             mAnimDrawable.start(); 
  51.  
  52.             // 播放結(jié)束后,刪除該bubbleLayout 
  53.             mHandler.postDelayed(new Runnable() { 
  54.                 @Override 
  55.                 public void run() { 
  56.                     mWm.removeView(bubbleLayout); 
  57.                 } 
  58.             }, 501); 
  59.         } 
  60.     }  

***附上完整demo地址:https://github.com/Horrarndoo/GooView 

責任編輯:龐桂玉 來源: Android開發(fā)中文站
相關推薦

2015-09-07 10:57:38

qq未讀消息

2011-06-20 16:03:03

Qt 控件 鼠標

2011-07-05 18:51:51

QT 控件 鼠標

2015-02-11 17:49:35

Android源碼自定義控件

2014-09-24 11:42:46

AndroidButton

2013-04-19 10:14:24

2009-06-08 20:13:36

Eclipse自定義控

2015-01-22 15:59:07

Android源碼日期時間控件SelectTime

2013-03-28 10:58:30

自定義Android界android

2013-01-06 10:43:54

Android開發(fā)View特效

2017-02-17 09:37:12

Android自定義控件方法總結(jié)

2011-12-16 14:23:51

Java

2016-11-16 21:55:55

源碼分析自定義view androi

2016-12-26 15:25:59

Android自定義View

2009-08-03 13:34:06

自定義C#控件

2009-08-03 13:39:46

C#自定義用戶控件

2009-09-03 13:34:03

.NET自定義控件

2022-06-30 14:02:07

鴻蒙開發(fā)消息彈窗組件

2010-08-03 16:13:01

FlexBuilder

2009-07-28 09:32:41

ASP.NET自定義控
點贊
收藏

51CTO技術棧公眾號