Android Map Api 使用和开发(2) 定位我的位置、地图弹出泡泡、通过经纬度获取地址...

本文详细介绍了地图应用中地图弹出泡泡显示信息、自动定位当前位置、获取经纬度对应地址名称等功能的实现方法,包括地图弹出泡泡的制作、自定义地图层、GPS与基站定位、以及主界面逻辑等关键步骤。

(全部源码地址:http://download.youkuaiyun.com/detail/totogo2010/4335701  ) 

 上篇把界面画出来了, 接下来就是显示里面的功能了,那这篇内容就比较丰富了。

主要有这么几道菜:

1、在地图上弹出泡泡显示信息,并且能相应泡泡的点击时间

2、自动定位当前位置(也就是我的位置) --添加了 GPS定位和基站定位。

3、获取经纬度对应的接到地址名称

 

那下面就开始代码把,理论知识能讲多少是多少。

一 、 地图弹出泡泡的制作

 

1 、overlay_popup.xml  直接把layout放出来

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:background="@drawable/bubble_background" android:layout_height="wrap_content"
	android:layout_width="wrap_content" android:id="@+id/map_bubblebtn"
	android:clickable="true" android:focusable="true" android:paddingTop="5dp"
	android:paddingLeft="5dp" android:paddingRight="5dp"
	android:paddingBottom="10dp">
    <LinearLayout android:orientation="vertical" android:id="@+id/popuptext"
	android:layout_width="wrap_content" android:layout_height="wrap_content">
        <TextView android:id="@+id/map_bubbleTitle" 
	       android:ellipsize="marquee" 
	       android:textSize="17sp"
	       android:textColor="#000000"
	       android:layout_width="wrap_content" 
	       android:layout_height="wrap_content"
	       android:singleLine="true" 
	      />
	    <TextView  android:id="@+id/map_bubbleText" 
	       android:textSize="14sp"
	       android:textColor="#000000"
	       android:layout_width="wrap_content" 
	       android:layout_height="wrap_content" 
	       android:layout_below="@id/map_bubbleTitle" 
	        />       
    </LinearLayout>
    
    <TextView android:layout_toRightOf="@id/popuptext" android:layout_width="wrap_content" 
	          android:layout_height="wrap_content"
	          android:background="@drawable/expander_ic_minimized"
	       />
</RelativeLayout>
 

 

还有泡泡的效果图 ,很多同学做项目都是时间很紧张的,别人贴出来代码都觉得不够直观,有截图是王道,

顺应大部分懒人的习惯,我编截图边发:

 

 

  

看到了吧, 泡泡上有title ,有 desc ,还有一个小icon。我把整个layout 设置成:

android:clickable="true" android:focusable="true"

这样这个layout就相当余一个button了,可以点击。

2、那代码怎么实现呢? FzMapActivity里加入下面代码

private void initPopView(){
    	if(null == popView){
			popView = getLayoutInflater().inflate(R.layout.overlay_popup, null);
			mapView.addView(popView, new MapView.LayoutParams(
					MapView.LayoutParams.WRAP_CONTENT,
					MapView.LayoutParams.WRAP_CONTENT, null,
					MapView.LayoutParams.BOTTOM_CENTER));
			popView.setVisibility(View.GONE);
    	}
       
    }
 

在进入主界面是 初始化一下view。

private View popView;当然这个变量定义也不能少。

3、自定义 itemizedOverlay     MyItemizedOverlay

好把,先把代码放出来,光描述怎么写太费劲了。

package com.android.fzmap.map;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.fzmap.FzMapActivity;
import com.android.fzmap.R;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.ItemizedOverlay.OnFocusChangeListener;
@SuppressWarnings("rawtypes")
public class MyItemizedOverlay extends ItemizedOverlay implements OnFocusChangeListener,OnClickListener{
	private static final String TAG = "MyItemizedOverlay";
	private List<OverlayItem> overlays = new ArrayList<OverlayItem>();
	private FzMapActivity mContext;
	private GeoPoint point = null;
	private String desc = "";
	private String car_title = "";
	private int layout_x = 0; // 用于设置popview 相对某个位置向x轴偏移
	private int layout_y = -30; // 用于设置popview 相对某个位置向x轴偏移
	
	private MapView mMapView;
	private MapController mMapCtrl;
	private View mPopView;
	
	private Drawable itemDrawable;
	private Drawable itemSelectDrawable;
	private OverlayItem selectItem;
	private OverlayItem lastItem;
	public void setItemSelectDrawable(Drawable itemSelectDrawable) {
		this.itemSelectDrawable = itemSelectDrawable;
	}
	public MyItemizedOverlay(Drawable defaultMarker) {
		super(boundCenterBottom(defaultMarker));
	}
	public MyItemizedOverlay(Drawable defaultMarker, Context context, MapView mapView, View popView, MapController mapCtrl) {
		super(boundCenterBottom(defaultMarker));
		itemDrawable = defaultMarker;
		itemSelectDrawable = defaultMarker;
		mContext = (FzMapActivity) context;
		setOnFocusChangeListener(this);
		layout_x = itemDrawable.getBounds().centerX();
		layout_y = - itemDrawable.getBounds().height();
		mMapView =  mapView;
		mPopView = popView;
		mMapCtrl = mapCtrl;
	}
	@Override
	protected OverlayItem createItem(int i) {
		return overlays.get(i);
	}
	@Override
	public int size() {
		return overlays.size();
	}
	public void addOverlay(OverlayItem item) {
		overlays.add(item);
		populate();
	}
	public void removeOverlay(int location) {
		overlays.remove(location);
	}
	@Override
	public boolean onTap(GeoPoint p, MapView mapView) {
		return super.onTap(p, mapView);
	}
	@Override
	protected boolean onTap(int index) {
		return super.onTap(index);
	}
	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow) {
		super.draw(canvas, mapView, shadow);
	}
	@Override
	public void onFocusChanged(ItemizedOverlay overlay, OverlayItem newFocus) {
		Log.d(TAG , "item focus changed!");
		if (null != newFocus) {
			Log.d(TAG , "centerY : " + itemDrawable.getBounds().centerY() + "; centerX :" + itemDrawable.getBounds().centerX());
			Log.d(TAG , " height : " + itemDrawable.getBounds().height());
			MapView.LayoutParams params = (MapView.LayoutParams) mPopView.getLayoutParams();
			params.x = this.layout_x;//Y轴偏移
			params.y = this.layout_y;//Y轴偏移
			point = newFocus.getPoint();
			params.point = point;
			mMapCtrl.animateTo(point);
			TextView title_TextView = (TextView) mPopView.findViewById(R.id.map_bubbleTitle);
			title_TextView.setText(newFocus.getTitle());
			TextView desc_TextView = (TextView) mPopView.findViewById(R.id.map_bubbleText);
			if(null == newFocus.getSnippet() || "".equals(newFocus.getSnippet())){
				desc_TextView.setVisibility(View.GONE);
			}else{
				this.desc = newFocus.getSnippet();
				desc_TextView.setText(this.desc);
				desc_TextView.setVisibility(View.VISIBLE);
			}
			RelativeLayout button = (RelativeLayout) mPopView.findViewById(R.id.map_bubblebtn);
			button.setOnClickListener(this);
			mMapView.updateViewLayout(mPopView, params);
			mPopView.setVisibility(View.VISIBLE);
			selectItem = newFocus;
		}
	}
	
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		}
	}
	
}
 

主要是继承  OnFocusChangeListener  监听地图层的变化, 为了方便监听button事件也继承了OnClickListener。

下面这方法监听这个层改变的时间,把泡泡弹出来。 

public void onFocusChanged(ItemizedOverlay overlay, OverlayItem newFocus) {

Log.d(TAG , "item focus changed!");

if (null != newFocus) {

Log.d(TAG , "centerY : " + itemDrawable.getBounds().centerY() + "; centerX :" + itemDrawable.getBounds().centerX());

Log.d(TAG , " height : " + itemDrawable.getBounds().height());

MapView.LayoutParams params = (MapView.LayoutParams) mPopView.getLayoutParams();

params.x = this.layout_x;//Y轴偏移

params.y = this.layout_y;//Y轴偏移

point = newFocus.getPoint();

params.point = point;

mMapCtrl.animateTo(point);

TextView title_TextView = (TextView) mPopView.findViewById(R.id.map_bubbleTitle);

title_TextView.setText(newFocus.getTitle());

TextView desc_TextView = (TextView) mPopView.findViewById(R.id.map_bubbleText);

if(null == newFocus.getSnippet() || "".equals(newFocus.getSnippet())){

desc_TextView.setVisibility(View.GONE);

}else{

desc = newFocus.getSnippet();

desc_TextView.setText(desc);

desc_TextView.setVisibility(View.VISIBLE);

}

RelativeLayout button = (RelativeLayout) mPopView.findViewById(R.id.map_bubblebtn);

button.setOnClickListener(this);

mMapView.updateViewLayout(mPopView, params);

mPopView.setVisibility(View.VISIBLE);

selectItem = newFocus;

}

 

}

 

二、长按地图获取地图位置并弹出泡泡显示信息


它的继承关系  LongPressOverlay extends Overlay implements OnDoubleTapListener

LongPressOverlay这个层主要是用来接收长按事件 和双击地图界面的

 

package com.android.fzmap.map;
import android.os.Handler;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import com.android.fzmap.FzMapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
public class LongPressOverlay extends Overlay implements OnDoubleTapListener,OnGestureListener{
	private FzMapActivity mContext;
	private MapView mMapView;
	private Handler mHandler;
	private MapController mMapCtrl;
	private GestureDetector gestureScanner = new GestureDetector(this);
	private int level = 0;
	
	public LongPressOverlay(FzMapActivity context, MapView mapView, Handler handler,MapController mapCtrl){
		mContext = context;
		mMapView = mapView;
		mHandler = handler;
		mMapCtrl = mapCtrl;
	}
	
	
	@Override
	public boolean onTouchEvent(MotionEvent event, MapView mapView) {
		return gestureScanner.onTouchEvent(event);
	}
	@Override
	public boolean onSingleTapConfirmed(MotionEvent e) {
		return false;
	}
	@Override
	public boolean onDoubleTap(MotionEvent e) {
		return false;
	}
	@Override
	public boolean onDoubleTapEvent(MotionEvent e) {
		if(++level % 3 == 0){
			mMapCtrl.zoomIn();
			level = 0;
		}
		return false;
	}
	@Override
	public boolean onDown(MotionEvent e) {
		return false;
	}
	@Override
	public void onShowPress(MotionEvent e) {
		
	}
	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		return false;
	}
	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		return false;
	}
	@Override
	public void onLongPress(MotionEvent e) {
		mContext.locPoint = mMapView.getProjection().fromPixels((int) e.getX(),
				(int) e.getY());
		mHandler.sendEmptyMessage(mContext.MSG_VIEW_LONGPRESS);
	}
	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		return false;
	}
}
 

 @Override

public void onLongPress(MotionEvent e) {

mContext.locPoint = mMapView.getProjection().fromPixels((int) e.getX(),

(int) e.getY());

mHandler.sendEmptyMessage(mContext.MSG_VIEW_LONGPRESS);

}接收到长按事件后给主界面发消息,由主界面处理。


三、FzLocationManager 这个类用来做gps,基站定位

package com.android.fzmap.map;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
/**
 * @author why
 */
public class FzLocationManager {
	private final String TAG = "FzLocationManager";
	private static Context mContext;
	private LocationManager gpsLocationManager;
	private LocationManager networkLocationManager;
	private static final int MINTIME = 2000;
	private static final int MININSTANCE = 2;
	private static FzLocationManager instance;
	private Location lastLocation = null;
	private static LocationCallBack mCallback;
	
	public static void init(Context c , LocationCallBack callback) {
		mContext = c;
		mCallback = callback;
	}
	
	private FzLocationManager() {
		// Gps 定位
		gpsLocationManager = (LocationManager) mContext
				.getSystemService(Context.LOCATION_SERVICE);
		Location gpsLocation = gpsLocationManager
				.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		gpsLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				MINTIME, MININSTANCE, locationListener);
        // 基站定位
		networkLocationManager = (LocationManager) mContext
				.getSystemService(Context.LOCATION_SERVICE);
		Location networkLocation = gpsLocationManager
				.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		networkLocationManager.requestLocationUpdates(
				LocationManager.NETWORK_PROVIDER, MINTIME, MININSTANCE,
				locationListener);
	}
	public static FzLocationManager getInstance() {
		if (null == instance) {
			instance = new FzLocationManager();
		}
		return instance;
	}
	private void updateLocation(Location location) {
		lastLocation = location;
		mCallback.onCurrentLocation(location);
	}
	
	private final LocationListener locationListener = new LocationListener() {
		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
		}
		@Override
		public void onProviderEnabled(String provider) {
		}
		@Override
		public void onProviderDisabled(String provider) {
		}
		@Override
		public void onLocationChanged(Location location) {
			Log.d(TAG, "onLocationChanged");
			updateLocation(location);
		}
	};
	public Location getMyLocation() {
		return lastLocation;
	}
	
    private static int ENOUGH_LONG = 1000 * 60;	 
	
	public interface LocationCallBack{
		/**
		 * 当前位置
		 * @param location 
		 */
		void onCurrentLocation(Location location);
	}
	
	
	public void destoryLocationManager(){
		Log.d(TAG, "destoryLocationManager");
		gpsLocationManager.removeUpdates(locationListener);
		networkLocationManager.removeUpdates(locationListener);
	}
}
 

 

public interface LocationCallBack{

/**

* 当前位置

* @param location 

*/

void onCurrentLocation(Location location);

}

定义一个接口 ,当监听到位置变化时,回调主界面

 

 

 

//locationListener注册监听器到位置服务管理里

 

networkLocationManager.requestLocationUpdates(

LocationManager.NETWORK_PROVIDER, MINTIME, MININSTANCE,

locationListener);

//位置信息变化回调

private void updateLocation(Location location) {

lastLocation = location;

mCallback.onCurrentLocation(location);

}

  

四、主界面逻辑

主界面有

package com.android.fzmap;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageButton;
import android.widget.TextView;
import com.android.fzmap.map.FzLocationManager;
import com.android.fzmap.map.FzLocationManager.LocationCallBack;
import com.android.fzmap.map.LongPressOverlay;
import com.android.fzmap.map.MyItemizedOverlay;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.android.fzmap.R;

public class FzMapActivity  extends MapActivity implements LocationCallBack ,OnClickListener{
    /** Called when the activity is first created. */
	private final String TAG = "FzMapActivity";
	private MapView mapView;
	private MapController mMapCtrl;
	private View popView;
	private Drawable myLocationDrawable;
	private Drawable mylongPressDrawable;
	private FzLocationManager fzLocation;
	private MyItemizedOverlay myLocationOverlay;
	private MyItemizedOverlay mLongPressOverlay;
	private List<Overlay> mapOverlays;
	private OverlayItem overlayitem = null;
	public GeoPoint locPoint;
	
	ImageButton loction_Btn;
	ImageButton layer_Btn;
	ImageButton pointwhat_Btn;
	
	public final int MSG_VIEW_LONGPRESS = 10001;
	public final int MSG_VIEW_ADDRESSNAME = 10002;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main);
        
        loction_Btn = (ImageButton)findViewById(R.id.loction);
    	layer_Btn = (ImageButton)findViewById(R.id.layer);
    	pointwhat_Btn = (ImageButton)findViewById(R.id.pointwhat);
        
    	loction_Btn.setOnClickListener(this);
    	layer_Btn.setOnClickListener(this);
    	pointwhat_Btn.setOnClickListener(this);
    	
        myLocationDrawable = getResources().getDrawable(R.drawable.point_where);
        mylongPressDrawable = getResources().getDrawable(R.drawable.point_start);
        
        mapView = (MapView) findViewById(R.id.map_view);
		mapView.setBuiltInZoomControls(true);
		mapView.setClickable(true);
		initPopView();
		mMapCtrl = mapView.getController();
		myLocationOverlay = new MyItemizedOverlay(myLocationDrawable,this, mapView, popView, mMapCtrl);
		mLongPressOverlay = new MyItemizedOverlay(mylongPressDrawable,this, mapView, popView, mMapCtrl);
		mapOverlays = mapView.getOverlays();
		mapOverlays.add(new LongPressOverlay(this, mapView, mHandler, mMapCtrl));
		//以北京市中心为中心
		GeoPoint cityLocPoint = new GeoPoint(39909230, 116397428);
		mMapCtrl.animateTo(cityLocPoint);
		mMapCtrl.setZoom(12);
		FzLocationManager.init(FzMapActivity.this.getApplicationContext() , FzMapActivity.this);
		fzLocation = FzLocationManager.getInstance();
		
    }
    
    
    private void initPopView(){
    	if(null == popView){
			popView = getLayoutInflater().inflate(R.layout.overlay_popup, null);
			mapView.addView(popView, new MapView.LayoutParams(
					MapView.LayoutParams.WRAP_CONTENT,
					MapView.LayoutParams.WRAP_CONTENT, null,
					MapView.LayoutParams.BOTTOM_CENTER));
			popView.setVisibility(View.GONE);
    	}
       
    }
    
	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
	
	@Override
	public void onCurrentLocation(Location location) {
		Log.d(TAG, "onCurrentLocationy");
		GeoPoint point = new GeoPoint(
				(int) (location.getLatitude() * 1E6),
				(int) (location.getLongitude() * 1E6));
		overlayitem = new OverlayItem(point, "我的位置", "");
		mMapCtrl.setZoom(16);
		if(myLocationOverlay.size() > 0){
			myLocationOverlay.removeOverlay(0);
		}
		myLocationOverlay.addOverlay(overlayitem);
		mapOverlays.add(myLocationOverlay);
		mMapCtrl.animateTo(point);
	}
	
	
	private String getLocationAddress(GeoPoint point){
		String add = "";
		Geocoder geoCoder = new Geocoder(getBaseContext(),
				Locale.getDefault());
		try {
			List<Address> addresses = geoCoder.getFromLocation(
					point.getLatitudeE6() / 1E6, point.getLongitudeE6() / 1E6, 1);
			Address address = addresses.get(0);
			int maxLine = address.getMaxAddressLineIndex();
			if(maxLine >= 2){
				add =  address.getAddressLine(1) + address.getAddressLine(2);
			}else {
				add = address.getAddressLine(1);
			}
		} catch (IOException e) {
			add = "";
			e.printStackTrace();
		}
		return add;
	}
	
	Runnable getAddressName = new Runnable() {
		@Override
		public void run() {
			String addressName = "";
			while(true){
				addressName = getLocationAddress(locPoint);
				Log.d(TAG, "获取地址名称");
				if(!"".equals(addressName)){
					break;
				}
			}
			Message msg = new Message();
			msg.what = MSG_VIEW_ADDRESSNAME;
			msg.obj = addressName;
			mHandler.sendMessage(msg);
		}
	};
	
	private Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MSG_VIEW_LONGPRESS:
				{
					if(null == locPoint) return;
					new Thread(getAddressName).start();
					overlayitem = new OverlayItem(locPoint, "地址名称",
							"正在地址加载...");
					if(mLongPressOverlay.size() > 0){
						mLongPressOverlay.removeOverlay(0);
					}
					popView.setVisibility(View.GONE);
					mLongPressOverlay.addOverlay(overlayitem);
					mLongPressOverlay.setFocus(overlayitem);
					mapOverlays.add(mLongPressOverlay);
					mMapCtrl.animateTo(locPoint);
					mapView.invalidate();
				}
				break;
			case MSG_VIEW_ADDRESSNAME:
				TextView desc = (TextView) popView.findViewById(R.id.map_bubbleText);
				desc.setText((String)msg.obj);
				popView.setVisibility(View.VISIBLE);
				break;
			}
		}
	};
			
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.loction:
		{
			
		}
			break;
		
		default:
			break;
		}
	}
	
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		fzLocation.destoryLocationManager();
	}
}
 

部分注释写在代码里了

 

最后再上一张截图,在室内通过基站定位到我的位置:

 

 

  

五、通过经纬度获取地址

这个单独拷贝出来让大家看看。这个方法获取地址有时候获取不到的,google好像对这个接口有限制。说白了就这这个接口不靠谱。

大家可以尝试用别的方法或手段获取地址

我的代码里加了个死循环去获取位置,这样的方案是不可取的,不过暂时用一下看看效果也好。

/**

* 通过经纬度获取地址

* @param point

* @return

*/

private String getLocationAddress(GeoPoint point){

String add = "";

Geocoder geoCoder = new Geocoder(getBaseContext(),

Locale.getDefault());

try {

List<Address> addresses = geoCoder.getFromLocation(

point.getLatitudeE6() / 1E6, point.getLongitudeE6() / 1E6, 1);

Address address = addresses.get(0);

int maxLine = address.getMaxAddressLineIndex();

if(maxLine >= 2){

add =  address.getAddressLine(1) + address.getAddressLine(2);

}else {

add = address.getAddressLine(1);

}

} catch (IOException e) {

add = "";

e.printStackTrace();

}

return add;

}

好了,以上是所有代码,  AndroidManifest.xml 在  (一)里有。

 

 

最后小结

用google的api获取到的位置放到他的地图上是有偏差的,而且偏差还比不小,大家可以观察一下,这个问题没有很好的免费解决方案。

如果有哪位有什么好建议可以发出来,谢谢。

用基站和gps定位,也没有处理那个是更好的定位的问题。

 

欢迎大家提建议

  

 

 

 

转载于:https://my.oschina.net/201003674/blog/288805

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值