绘图与缩略完成
This commit is contained in:
parent
3bcfc5a5da
commit
5e107028de
@ -49,7 +49,11 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// 二维码使用的类库
|
||||
// 卫星定位类库
|
||||
api 'com.google.android.gms:play-services-maps:18.1.0'
|
||||
api 'com.google.android.gms:play-services-location:21.0.1'
|
||||
|
||||
// 二维码使用的类库
|
||||
api 'com.google.zxing:core:3.4.1'
|
||||
api 'com.journeyapps:zxing-android-embedded:3.6.0'
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Fri Feb 21 17:45:58 GMT 2025
|
||||
#Sat Feb 22 11:42:07 GMT 2025
|
||||
stageCount=0
|
||||
libraryProject=
|
||||
baseVersion=1.0
|
||||
publishVersion=1.0.0
|
||||
buildCount=1
|
||||
buildCount=54
|
||||
baseBetaVersion=1.0.1
|
||||
|
@ -3,19 +3,33 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cc.winboll.studio.positions">
|
||||
|
||||
<!-- 只能在前台获取精确的位置信息 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
|
||||
<!-- 只能在前台获取大概位置(基于网络) -->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_winboll"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/MyAppTheme"
|
||||
android:supportsRtl="true">
|
||||
|
||||
android:supportsRtl="true"
|
||||
android:hardwareAccelerated="true">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:exported="true">
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activities.Main2Activity"
|
||||
android:label="@string/app_name"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
@ -26,9 +40,8 @@
|
||||
|
||||
</activity>
|
||||
|
||||
|
||||
<activity android:name="cc.winboll.studio.positions.activities.SettingsActivity"/>
|
||||
|
||||
|
||||
<service
|
||||
android:name="cc.winboll.studio.positions.services.MainService"
|
||||
android:exported="true"/>
|
||||
@ -44,7 +57,7 @@
|
||||
</intent-filter>
|
||||
|
||||
</receiver>
|
||||
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
|
@ -146,7 +146,7 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct
|
||||
void initData() {
|
||||
ViewPager viewPager = findViewById(R.id.activitymainViewPager1);
|
||||
LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||
View view1 = inflater.inflate(R.layout.fragment_call, viewPager, false);
|
||||
View view1 = inflater.inflate(R.layout.fragment_gms, viewPager, false);
|
||||
View view2 = inflater.inflate(R.layout.fragment_contacts, viewPager, false);
|
||||
View view3 = inflater.inflate(R.layout.fragment_log, viewPager, false);
|
||||
|
||||
|
@ -0,0 +1,40 @@
|
||||
package cc.winboll.studio.positions.activities;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/22 02:01:44
|
||||
*/
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import cc.winboll.studio.positions.R;
|
||||
import cc.winboll.studio.positions.views.GridMapView;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View;
|
||||
|
||||
public class Main2Activity extends AppCompatActivity {
|
||||
|
||||
GridMapView gridMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main2);
|
||||
|
||||
// 初始化视图
|
||||
GridMapView mapView = (GridMapView) findViewById(R.id.map_view);
|
||||
|
||||
// 设置网格参数
|
||||
mapView.setGridParameters(10000f, 10000f, 10f);
|
||||
|
||||
// 初始化显示区域(中心点400,300,显示范围200x200)
|
||||
mapView.initViewport(5000f, 5000f, 2000f, 2000f);
|
||||
|
||||
// 绘制图形
|
||||
mapView.drawPoint(5000f, 5000f, Color.RED, 8f);
|
||||
mapView.drawCircle(5000f, 5000f, 50f, Color.BLUE, 8f);
|
||||
mapView.drawLine(4975f, 4975f, 5025f, 5025f, Color.GREEN, 2f);
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import cc.winboll.studio.positions.fragments.CallFragment;
|
||||
import cc.winboll.studio.positions.fragments.GmsFragment;
|
||||
import cc.winboll.studio.positions.fragments.ContactsFragment;
|
||||
import cc.winboll.studio.positions.fragments.LogFragment;
|
||||
|
||||
@ -30,7 +30,7 @@ public class MyPagerAdapter extends FragmentPagerAdapter {
|
||||
} else if(position == 2) {
|
||||
return LogFragment.newInstance(position);
|
||||
} else {
|
||||
return CallFragment.newInstance(position);
|
||||
return GmsFragment.newInstance(position);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,17 +16,17 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class CallFragment extends Fragment {
|
||||
public class GmsFragment extends Fragment {
|
||||
|
||||
public static final String TAG = "CallFragment";
|
||||
public static final String TAG = "GmsFragment";
|
||||
|
||||
private static final String ARG_PAGE = "ARG_PAGE";
|
||||
private int mPage;
|
||||
|
||||
public static CallFragment newInstance(int page) {
|
||||
public static GmsFragment newInstance(int page) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_PAGE, page);
|
||||
CallFragment fragment = new CallFragment();
|
||||
GmsFragment fragment = new GmsFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
@ -43,7 +43,7 @@ public class CallFragment extends Fragment {
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_call, container, false);
|
||||
View view = inflater.inflate(R.layout.fragment_gms, container, false);
|
||||
TextView textView = view.findViewById(R.id.page_text);
|
||||
textView.setText("这是第 " + mPage + " 页");
|
||||
return view;
|
@ -0,0 +1,246 @@
|
||||
package cc.winboll.studio.positions.views;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/22 03:32:48
|
||||
* @Describe GridMapView
|
||||
*/
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PointF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.view.View;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GridMapView extends View {
|
||||
// 网格参数
|
||||
private float gridTotalWidth = 1000f;
|
||||
private float gridTotalHeight = 1000f;
|
||||
private float gridSpacing = 50f;
|
||||
|
||||
// 视图变换参数
|
||||
private float offsetX = 0f;
|
||||
private float offsetY = 0f;
|
||||
private float scaleFactor = 1.0f;
|
||||
private final float minScale = 0.5f;
|
||||
private final float maxScale = 5.0f;
|
||||
|
||||
// 手势检测
|
||||
private final ScaleGestureDetector scaleDetector;
|
||||
private float lastTouchX;
|
||||
private float lastTouchY;
|
||||
|
||||
// 图形存储
|
||||
private final List<MapShape> shapes = new ArrayList<MapShape>();
|
||||
|
||||
public GridMapView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public GridMapView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
scaleDetector = new ScaleGestureDetector(context, new ScaleListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
canvas.save();
|
||||
canvas.translate(offsetX, offsetY);
|
||||
canvas.scale(scaleFactor, scaleFactor);
|
||||
|
||||
drawGrid(canvas);
|
||||
drawShapes(canvas);
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
private void drawGrid(Canvas canvas) {
|
||||
Paint gridPaint = new Paint();
|
||||
gridPaint.setColor(Color.LTGRAY);
|
||||
gridPaint.setStrokeWidth(1f / scaleFactor);
|
||||
|
||||
// 绘制垂直线
|
||||
for (float x = 0; x <= gridTotalWidth; x += gridSpacing) {
|
||||
canvas.drawLine(x, 0, x, gridTotalHeight, gridPaint);
|
||||
}
|
||||
|
||||
// 绘制水平线
|
||||
for (float y = 0; y <= gridTotalHeight; y += gridSpacing) {
|
||||
canvas.drawLine(0, y, gridTotalWidth, y, gridPaint);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawShapes(Canvas canvas) {
|
||||
for (MapShape shape : shapes) {
|
||||
shape.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
scaleDetector.onTouchEvent(event);
|
||||
|
||||
final int action = event.getAction();
|
||||
final float x = event.getX();
|
||||
final float y = event.getY();
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (!scaleDetector.isInProgress()) {
|
||||
lastTouchX = x;
|
||||
lastTouchY = y;
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (!scaleDetector.isInProgress()) {
|
||||
final float dx = x - lastTouchX;
|
||||
final float dy = y - lastTouchY;
|
||||
|
||||
offsetX += dx;
|
||||
offsetY += dy;
|
||||
invalidate();
|
||||
|
||||
lastTouchX = x;
|
||||
lastTouchY = y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 初始化视图显示区域
|
||||
public void initViewport(final float centerX, final float centerY,
|
||||
final float viewWidth, final float viewHeight) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
float viewportWidth = getWidth();
|
||||
float viewportHeight = getHeight();
|
||||
|
||||
float widthScale = viewportWidth / viewWidth;
|
||||
float heightScale = viewportHeight / viewHeight;
|
||||
scaleFactor = Math.min(widthScale, heightScale);
|
||||
|
||||
offsetX = viewportWidth/2 - centerX * scaleFactor;
|
||||
offsetY = viewportHeight/2 - centerY * scaleFactor;
|
||||
invalidate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 图形绘制方法
|
||||
public void drawPoint(float x, float y, int color, float size) {
|
||||
shapes.add(new MapShape(MapShape.TYPE_POINT, x, y, color, size));
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void drawCircle(float x, float y, float radius, int color, float strokeWidth) {
|
||||
MapShape shape = new MapShape(MapShape.TYPE_CIRCLE, x, y, color, radius);
|
||||
shape.setStrokeWidth(strokeWidth);
|
||||
shapes.add(shape);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void drawLine(float startX, float startY, float endX, float endY,
|
||||
int color, float strokeWidth) {
|
||||
MapShape shape = new MapShape(MapShape.TYPE_LINE, startX, startY, endX, endY, color);
|
||||
shape.setStrokeWidth(strokeWidth);
|
||||
shapes.add(shape);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
// 网格参数设置
|
||||
public void setGridParameters(float totalWidth, float totalHeight, float spacing) {
|
||||
gridTotalWidth = totalWidth;
|
||||
gridTotalHeight = totalHeight;
|
||||
gridSpacing = spacing;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
float newScale = scaleFactor * detector.getScaleFactor();
|
||||
newScale = Math.max(minScale, Math.min(newScale, maxScale));
|
||||
|
||||
float focusX = detector.getFocusX();
|
||||
float focusY = detector.getFocusY();
|
||||
|
||||
offsetX = focusX - ((focusX - offsetX) / scaleFactor * newScale);
|
||||
offsetY = focusY - ((focusY - offsetY) / scaleFactor * newScale);
|
||||
|
||||
scaleFactor = newScale;
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MapShape {
|
||||
static final int TYPE_POINT = 0;
|
||||
static final int TYPE_CIRCLE = 1;
|
||||
static final int TYPE_LINE = 2;
|
||||
|
||||
final int type;
|
||||
final PointF[] points;
|
||||
final int color;
|
||||
float radius;
|
||||
float strokeWidth = 2f;
|
||||
|
||||
MapShape(int type, float x, float y, int color, float size) {
|
||||
this.type = type;
|
||||
this.points = new PointF[]{new PointF(x, y)};
|
||||
this.color = color;
|
||||
this.radius = size;
|
||||
}
|
||||
|
||||
MapShape(int type, float x1, float y1, float x2, float y2, int color) {
|
||||
this.type = type;
|
||||
this.points = new PointF[]{
|
||||
new PointF(x1, y1),
|
||||
new PointF(x2, y2)
|
||||
};
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
MapShape setStrokeWidth(float width) {
|
||||
this.strokeWidth = width;
|
||||
return this;
|
||||
}
|
||||
|
||||
void draw(Canvas canvas) {
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(color);
|
||||
|
||||
switch (type) {
|
||||
case TYPE_POINT:
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
canvas.drawCircle(points[0].x, points[0].y, radius, paint);
|
||||
break;
|
||||
|
||||
case TYPE_CIRCLE:
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(strokeWidth);
|
||||
canvas.drawCircle(points[0].x, points[0].y, radius, paint);
|
||||
break;
|
||||
|
||||
case TYPE_LINE:
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(strokeWidth);
|
||||
canvas.drawLine(
|
||||
points[0].x, points[0].y,
|
||||
points[1].x, points[1].y,
|
||||
paint
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
69
positions/src/main/res/layout/activity_main2.xml
Normal file
69
positions/src/main/res/layout/activity_main2.xml
Normal file
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="#FFB2B2B2">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_get_location"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="获取位置"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_latitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_longitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_altitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_speed"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_bearing"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<cc.winboll.studio.positions.views.GridMapView
|
||||
android:id="@+id/map_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
12
positions/src/main/res/values/attrs.xml
Normal file
12
positions/src/main/res/values/attrs.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="GridMapView">
|
||||
<attr name="columns" format="integer" />
|
||||
<attr name="rows" format="integer" />
|
||||
<attr name="spacing" format="dimension" />
|
||||
<attr name="initCenterX" format="float" />
|
||||
<attr name="initCenterY" format="float" />
|
||||
<attr name="initViewWidth" format="dimension" />
|
||||
<attr name="initViewHeight" format="dimension" />
|
||||
</declare-styleable>
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user