亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

模仿百度紅包福袋界面實(shí)例代碼

 更新時(shí)間:2016年02月03日 09:18:16   作者:Git_Android  
新年到新年到,紅包搶不停。在我搶紅包的時(shí)候意外的發(fā)現(xiàn)了百度的福袋界面挺不錯(cuò)的,于是抽時(shí)間專門(mén)寫(xiě)篇文章來(lái)完成百度紅包界面吧

新年到新年到,紅包搶不停。在我搶紅包的時(shí)候意外的發(fā)現(xiàn)了百度的福袋界面挺不錯(cuò)的,于是抽時(shí)間專門(mén)寫(xiě)篇文章來(lái)完成百度紅包界面吧。

當(dāng)然啦,這其實(shí)就是解鎖界面的進(jìn)化版本。不過(guò)其包含的知識(shí)點(diǎn)還是挺多的,寫(xiě)篇博文記錄一下看看具體有哪些技術(shù)點(diǎn)啦??纯窗俣鹊男Ч麍D:

1.編程思路

看看界面,不難發(fā)現(xiàn),其就是一個(gè)放入九張圖片的容器,繪制其實(shí)可以在其上面另創(chuàng)建一個(gè)透明View負(fù)責(zé)繪制線與圓圈。下面我們將介紹一下實(shí)現(xiàn)過(guò)程。

㈠自定義ViewGroup

我們知道,自定義ViewGroup一定需要實(shí)現(xiàn)其onLayout()方法。該方法是設(shè)置子View位置與尺寸的時(shí)候調(diào)用。還有一個(gè)onMeasure()方法,該方法是測(cè)量view及其內(nèi)容來(lái)確定view的寬度和高度。

㈡存儲(chǔ)其點(diǎn)與圓的位置及繪制參數(shù)

當(dāng)重回界面的時(shí)候,是不會(huì)保存上一次繪制界面的內(nèi)容,必須存儲(chǔ)以備重繪時(shí)候繪制到界面

㈢簡(jiǎn)單的縮放動(dòng)畫(huà)

㈣自定義View實(shí)現(xiàn)繪制界面

㈤繪制完成時(shí),清除界面繪制內(nèi)容,并且保證不連接重復(fù)圖片

下面我們將完成這些步驟。

2.自定義ViewGroup

開(kāi)始的任務(wù)就是將九張圖片平均分布到圖片的位置,顯示在手機(jī)界面中。其代碼如下:

public class LYJViewGroup extends ViewGroup implements LYJGestureDrawline.OnAnimationCallback{
/**
* 每個(gè)點(diǎn)區(qū)域的寬度
*/
private int childWidth;
/***
* 上下文
*/
private Context context;
/***
* 保存圖片點(diǎn)的位置
*/
private List<LYJGesturePoint> list;
/***
* 創(chuàng)建view使其在ViewGroup之上。
*/
private LYJGestureView gestureDrawline;
private int baseNum = 5;
public LYJViewGroup(Context context) {
super(context);
this.context = context;
this.list = new ArrayList<>();
DisplayMetrics metric = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metric);
childWidth = metric.widthPixels / 3; // 屏幕寬度(像素)
addChild();
// 初始化一個(gè)可以畫(huà)線的view
gestureDrawline = new LYJGestureView(context, list);
gestureDrawline.setAnimationCallback(this);
}
public void setParentView(ViewGroup parent){
// 得到屏幕的寬度
DisplayMetrics metric = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metric);
int width = metric.widthPixels;
LayoutParams layoutParams = new LayoutParams(width, width);
this.setLayoutParams(layoutParams);
gestureDrawline.setLayoutParams(layoutParams);
parent.addView(this);
parent.addView(gestureDrawline);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < getChildCount(); i++) {
//第幾行
int rowspan = i / 3;
//第幾列
int column = i % 3;
android.view.View v = getChildAt(i);
v.layout(column * childWidth + childWidth / baseNum, rowspan * childWidth + childWidth / baseNum,
column * childWidth + childWidth - childWidth / baseNum, rowspan * childWidth + childWidth - childWidth / baseNum);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 遍歷設(shè)置每個(gè)子view的大小
for (int i = 0; i < getChildCount(); i++) {
View v = getChildAt(i);
v.measure(widthMeasureSpec, heightMeasureSpec);
}
}
private void addChild() {
for (int i = 0; i < 9; i++) {
ImageView image = new ImageView(context);
image.setBackgroundResource(R.drawable.marker);
this.addView(image);
invalidate();
// 第幾行
int rowspan = i / 3;
// 第幾列
int column = i % 3;
// 定義點(diǎn)的左上角與右下角的坐標(biāo)
int leftX = column * childWidth + childWidth / baseNum;
int topY = rowspan * childWidth + childWidth / baseNum;
int rightX = column * childWidth + childWidth - childWidth / baseNum;
int bottomY = rowspan * childWidth + childWidth - childWidth / baseNum;
LYJGesturePoint p = new LYJGesturePoint(leftX, topY, rightX,bottomY,i);
this.list.add(p);
}
}
@Override
public void startAnimationImage(int i) {
Animation animation= AnimationUtils.loadAnimation(getContext(), R.anim.gridlayout_child_scale_anim);
getChildAt(i).startAnimation(animation);
}
}

3.自定義點(diǎn)類

顧名思義,就是為了獲取點(diǎn)的相關(guān)的屬性,其中基礎(chǔ)屬性圖片左上角坐標(biāo)與右下角坐標(biāo),計(jì)算圖片中心位置以便獲取圖片中心點(diǎn)。狀態(tài)標(biāo)記,表示該點(diǎn)是否繪制到圖片。下面是其實(shí)體類:

public class LYJGesturePoint {
private Point pointLeftTop;//左上角坐標(biāo)
private Point pointRightBottom;//右下角坐標(biāo)
private int centerX;//圖片中心點(diǎn)X坐標(biāo)
private int centerY;//圖片中心點(diǎn)Y坐標(biāo)
private int pointState;//是否點(diǎn)擊了該圖片
private int num;
public int getNum() {
return num;
}
public int getPointState() {
return pointState;
}
public void setPointState(int pointState) {
this.pointState = pointState;
}
public Point getPointLeftTop() {
return pointLeftTop;
}
public Point getPointRightBottom() {
return pointRightBottom;
}
public LYJGesturePoint(int left,int top,int right,int bottom,int i){
this.pointLeftTop=new Point(left,top);
this.pointRightBottom=new Point(right,bottom);
this.num=i;
}
public int getCenterX() {
this.centerX=(this.pointLeftTop.x+this.pointRightBottom.x)/2;
return centerX;
}
public int getCenterY() {
this.centerY=(this.pointLeftTop.y+this.pointRightBottom.y)/2;
return centerY;
}
}

4.自定義圓類

這個(gè)類較簡(jiǎn)單就三個(gè)屬性而已(圓中心點(diǎn)坐標(biāo)及半徑),代碼如下:

public class LYJCirclePoint {
private int roundX;//圓中心點(diǎn)X坐標(biāo)
private int roundY;//圓中心點(diǎn)Y坐標(biāo)
private int radiu;//圓半徑
public int getRadiu() {
return radiu;
}
public int getRoundX() {
return roundX;
}
public int getRoundY() {
return roundY;
}
public LYJCirclePoint(int roundX,int roundY,int radiu){
this.roundX=roundX;
this.roundY=roundY;
this.radiu=radiu;
}
}

5.實(shí)現(xiàn)自定義繪制類View

代碼如下:

public class LYJGestureView extends android.view.View {
/***
* 聲明直線畫(huà)筆
*/
private Paint paint;
/***
* 聲明圓圈畫(huà)筆
*/
private Paint circlePaint;
/***
* 畫(huà)布
*/
private Canvas canvas;
/***
* 位圖
*/
private Bitmap bitmap;
/***
* 裝有各個(gè)view坐標(biāo)的集合,用于判斷點(diǎn)是否在其中
*/
private List<LYJGesturePoint> list;
/***
* 記錄畫(huà)過(guò)的線
*/
private List<Pair<LYJGesturePoint, LYJGesturePoint>> lineList;
/***
* 記錄畫(huà)過(guò)的圓
*/
private List<LYJCirclePoint> circlePoints;
/**
* 手指當(dāng)前在哪個(gè)Point內(nèi)
*/
private LYJGesturePoint currentPoint;
/***
* 手指按下動(dòng)畫(huà)
*/
private OnAnimationCallback animationCallback;
public interface OnAnimationCallback{
public void startAnimationImage(int i);
}
public void setAnimationCallback(OnAnimationCallback animationCallback) {
this.animationCallback = animationCallback;
}
public LYJGestureView(Context context, List<LYJGesturePoint> list){
super(context);
Log.i(getClass().getName(), "GestureDrawline");
paint = new Paint(Paint.DITHER_FLAG);// 創(chuàng)建一個(gè)畫(huà)筆
circlePaint=new Paint(Paint.DITHER_FLAG);
DisplayMetrics metric = new DisplayMetrics();
((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(metric);
Log.i(getClass().getName(), "widthPixels" + metric.widthPixels);
Log.i(getClass().getName(), "heightPixels" + metric.heightPixels);
bitmap = Bitmap.createBitmap(metric.widthPixels, metric.heightPixels, Bitmap.Config.ARGB_8888); // 設(shè)置位圖的寬高
canvas = new Canvas();
canvas.setBitmap(bitmap);
paint.setStyle(Paint.Style.STROKE);// 設(shè)置非填充
paint.setStrokeWidth(20);// 筆寬20像素
paint.setColor(Color.rgb(245, 142, 33));// 設(shè)置默認(rèn)連線顏色
paint.setAntiAlias(true);// 不顯示鋸齒
circlePaint.setStyle(Paint.Style.FILL);
circlePaint.setStrokeWidth(1);
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.rgb(245, 142, 33));
this.list = list;
this.lineList = new ArrayList<>();
this.circlePoints=new ArrayList<>();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
// 判斷當(dāng)前點(diǎn)擊的位置是處于哪個(gè)點(diǎn)之內(nèi)
currentPoint = getPointAt((int) event.getX(), (int) event.getY());
if (currentPoint != null) {
currentPoint.setPointState(Constants.POINT_STATE_SELECTED);
this.animationCallback.startAnimationImage(currentPoint.getNum());
canvas.drawCircle(currentPoint.getCenterX(), currentPoint.getCenterY(), 20, circlePaint);
circlePoints.add(new LYJCirclePoint(currentPoint.getCenterX(),currentPoint.getCenterY(),20));
}
invalidate();
break;
case MotionEvent.ACTION_MOVE:
clearScreenAndDrawList();
// 得到當(dāng)前移動(dòng)位置是處于哪個(gè)點(diǎn)內(nèi)
LYJGesturePoint pointAt = getPointAt((int) event.getX(), (int) event.getY());
if (currentPoint == null && pointAt == null) {//你把手指按在屏幕滑動(dòng),如果終點(diǎn)與起點(diǎn)都不圖片那么返回
return true;
} else {// 代表用戶的手指移動(dòng)到了點(diǎn)上
if (currentPoint == null) {// 先判斷當(dāng)前的point是不是為null
// 如果為空,那么把手指移動(dòng)到的點(diǎn)賦值給currentPoint
currentPoint = pointAt;
// 把currentPoint這個(gè)點(diǎn)設(shè)置選中狀態(tài);
currentPoint.setPointState(Constants.POINT_STATE_SELECTED);
}
}
//如果移動(dòng)到的點(diǎn)不為圖片區(qū)域或者移動(dòng)到自己的地方,或者該圖片已經(jīng)為選中狀態(tài),直接畫(huà)直線就可以了
if(pointAt == null || currentPoint.equals(pointAt) || Constants.POINT_STATE_SELECTED == pointAt.getPointState()){
canvas.drawCircle(currentPoint.getCenterX(), currentPoint.getCenterY(), 20, circlePaint);
circlePoints.add(new LYJCirclePoint(currentPoint.getCenterX(), currentPoint.getCenterY(), 20));
canvas.drawLine(currentPoint.getCenterX(), currentPoint.getCenterY(), event.getX(), event.getY(), paint);
}else{//其他情況畫(huà)兩點(diǎn)相連直線,并且保存繪制圓與直線,并調(diào)用按下圖片的縮放動(dòng)畫(huà)
canvas.drawCircle(pointAt.getCenterX(),pointAt.getCenterY(),20,circlePaint);
circlePoints.add(new LYJCirclePoint(pointAt.getCenterX(), pointAt.getCenterY(), 20));
this.animationCallback.startAnimationImage(pointAt.getNum());
pointAt.setPointState(Constants.POINT_STATE_SELECTED);
canvas.drawLine(currentPoint.getCenterX(), currentPoint.getCenterY(), pointAt.getCenterX(), pointAt.getCenterY(), paint);
Pair<LYJGesturePoint, LYJGesturePoint> pair = new Pair<>(currentPoint, pointAt);
lineList.add(pair);
currentPoint=pointAt;//設(shè)置選中點(diǎn)為當(dāng)前點(diǎn)。
}
invalidate();//重繪
break;
case MotionEvent.ACTION_UP:
clearScreenAndDrawList();//防止多出一條沒(méi)有終點(diǎn)的直線
new Handler().postDelayed(new clearLineRunnable(), 1000);//1秒后清空繪制界面
invalidate();//重繪
break;
default:
break;
}
return true;
}
class clearLineRunnable implements Runnable {
public void run() {
// 清空保存點(diǎn)與圓的集合
lineList.clear();
circlePoints.clear();
// 重新繪制界面
clearScreenAndDrawList();
for (LYJGesturePoint p : list) {
//設(shè)置其為初始化不選中狀態(tài)
p.setPointState(Constants.POINT_STATE_NORMAL);
}
invalidate();
}
}
/**
* 通過(guò)點(diǎn)的位置去集合里面查找這個(gè)點(diǎn)是包含在哪個(gè)Point里面的
*
* @param x
* @param y
* @return 如果沒(méi)有找到,則返回null,代表用戶當(dāng)前移動(dòng)的地方屬于點(diǎn)與點(diǎn)之間
*/
private LYJGesturePoint getPointAt(int x, int y) {
for (LYJGesturePoint point : list) {
// 先判斷點(diǎn)是否在圖片的X坐標(biāo)內(nèi)
int leftX = point.getPointLeftTop().x;
int rightX = point.getPointRightBottom().x;
if (!(x >= leftX && x < rightX)) {
// 如果為假,則跳到下一個(gè)對(duì)比
continue;
}
//在判斷點(diǎn)是否在圖片的Y坐標(biāo)內(nèi)
int topY = point.getPointLeftTop().y;
int bottomY = point.getPointRightBottom().y;
if (!(y >= topY && y < bottomY)) {
// 如果為假,則跳到下一個(gè)對(duì)比
continue;
}
// 如果執(zhí)行到這,那么說(shuō)明當(dāng)前點(diǎn)擊的點(diǎn)的位置在遍歷到點(diǎn)的位置這個(gè)地方
return point;
}
return null;
}
/**
* 清掉屏幕上所有的線,然后畫(huà)出集合里面的線
*/
private void clearScreenAndDrawList() {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
for (Pair<LYJGesturePoint, LYJGesturePoint> pair : lineList) {
canvas.drawLine(pair.first.getCenterX(), pair.first.getCenterY(),
pair.second.getCenterX(), pair.second.getCenterY(), paint);// 畫(huà)線
}
for(LYJCirclePoint lyjCirclePoint : circlePoints){
canvas.drawCircle(lyjCirclePoint.getRoundX(),lyjCirclePoint.getRoundY(), lyjCirclePoint.getRadiu(),circlePaint);
}
}
//繪制用bitmap創(chuàng)建出來(lái)的畫(huà)布
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
}
}

這樣就可以得到如下界面效果(當(dāng)然反編譯百度錢(qián)包,并沒(méi)有百度錢(qián)包中的圖片,只好隨便找了一張圖片):

相關(guān)文章

  • SpringBoot實(shí)現(xiàn)嵌入式 Servlet容器

    SpringBoot實(shí)現(xiàn)嵌入式 Servlet容器

    傳統(tǒng)的Spring MVC工程部署時(shí)需要將WAR文件放置在servlet容器的文檔目錄內(nèi),而Spring Boot工程使用嵌入式servlet容器省去了這一步驟,本文就來(lái)設(shè)置一下相關(guān)配置,感興趣的可以了解一下
    2023-12-12
  • Mybatis參數(shù)(Parameters)傳遞方式

    Mybatis參數(shù)(Parameters)傳遞方式

    這篇文章主要介紹了Mybatis參數(shù)(Parameters)傳遞方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java排序算法之桶排序詳解

    Java排序算法之桶排序詳解

    這篇文章主要介紹了Java排序算法之桶排序詳解,桶排序是將數(shù)組中的元素放到一個(gè)一個(gè)的桶中,每個(gè)桶(bucket)代表一個(gè)區(qū)間,里面可以承載一個(gè)或者多個(gè)元素,然后將桶內(nèi)的元素進(jìn)行排序,再按順序遍歷桶,輸出桶內(nèi)元素,需要的朋友可以參考下
    2023-10-10
  • 一文詳解Java中的類加載機(jī)制

    一文詳解Java中的類加載機(jī)制

    Java虛擬機(jī)把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)、轉(zhuǎn)換解析和初始化,最終形成可以被虛擬機(jī)直接使用的Java類型,這個(gè)過(guò)程被稱作虛擬機(jī)的類加載機(jī)制。本文將詳解Java的類加載機(jī)制,需要的可以參考一下
    2022-05-05
  • java實(shí)現(xiàn)簡(jiǎn)單撲克牌游戲

    java實(shí)現(xiàn)簡(jiǎn)單撲克牌游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單撲克牌游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • Java8?stream流分組groupingBy的使用方法代碼

    Java8?stream流分組groupingBy的使用方法代碼

    對(duì)于java8的新特性groupingBy方法,相信有很多人都在工作中用過(guò),這篇文章主要給大家介紹了關(guān)于Java8?stream流分組groupingBy的使用方法,需要的朋友可以參考下
    2024-01-01
  • Jmeter后置處理器實(shí)現(xiàn)過(guò)程及方法應(yīng)用

    Jmeter后置處理器實(shí)現(xiàn)過(guò)程及方法應(yīng)用

    這篇文章主要介紹了Jmeter后置處理器實(shí)現(xiàn)過(guò)程及方法應(yīng)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • springboot @WebFilter注解過(guò)濾器的實(shí)現(xiàn)

    springboot @WebFilter注解過(guò)濾器的實(shí)現(xiàn)

    這篇文章主要介紹了springboot @WebFilter注解過(guò)濾器的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • springboot全局字符編碼設(shè)置解決亂碼問(wèn)題

    springboot全局字符編碼設(shè)置解決亂碼問(wèn)題

    這篇文章主要介紹了springboot全局字符編碼設(shè)置解決亂碼問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • SpringBoot環(huán)境配置知識(shí)總結(jié)

    SpringBoot環(huán)境配置知識(shí)總結(jié)

    今天帶大家了解SpringBoot環(huán)境配置的相關(guān)知識(shí),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05

最新評(píng)論