<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android實(shí)現(xiàn)四色填充地圖功能

          共 17446字,需瀏覽 35分鐘

           ·

          2022-07-07 22:14

          先上效果圖:



          明顯是一個(gè)自定義view,先解析svg資源(該資源不嚴(yán)謹(jǐn),請(qǐng)勿在正規(guī)),獲取每個(gè)省的path,再用四色算法設(shè)置每個(gè)省的顏色,先列舉主要方法解析svg文件

           InputStream inputStream = context.getResources().openRawResource(R.raw.china);            proviceItems = new ArrayList<>();            try {                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();                DocumentBuilder builder = null;                builder = factory.newDocumentBuilder();                Document document = builder.parse(inputStream);                Element rootElement = document.getDocumentElement();                NodeList items = rootElement.getElementsByTagName("path");


          items就是每個(gè)省份的邊框了,遍歷全部省份確定地圖的最左最右最上最下,從而確定地圖的真正寬高,然后再對(duì)比自定義View的寬度,確定畫圖的縮放比例,再定義自定義View的高度

              @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int width = MeasureSpec.getSize(widthMeasureSpec);        if (totalRect != null && width != 0) {            //獲取到地圖的矩形的寬度            double mapWidth = totalRect.width();            //獲取到比例值            scale = (float) (width / mapWidth);            //用寬度重新定義高度            heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (totalRect.height() * scale), MeasureSpec.EXACTLY);        }        super.onMeasure(widthMeasureSpec,heightMeasureSpec);    }

          重寫onDraw方法,把每個(gè)省依次華進(jìn)去,如果有點(diǎn)擊事件,被點(diǎn)擊有變化的話,多數(shù)情況下都是要最后一個(gè)話

             @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (proviceItems != null) {            int tatalNum = proviceItems.size();            canvas.save();            canvas.scale(scale, scale);            ProviceItem selsetProviceItem = null;            // 先畫沒被選中的            for (int i = 0; i < tatalNum; i++) {                if (!proviceItems.get(i).isSelect()) {                    proviceItems.get(i).drawItem(canvas, paint);                } else {                    selsetProviceItem = proviceItems.get(i);                }            }            //被選中的最后畫,因?yàn)楸贿x中的有陰影            if (selsetProviceItem != null) {                selsetProviceItem.drawItem(canvas, paint);            }        }    }

          把每個(gè)省都畫到地圖上的方法

           paint.setStrokeWidth(1);        paint.setColor(drawColor);        paint.setStyle(Paint.Style.FILL_AND_STROKE);        canvas.drawPath(path, paint);        if (isSelect) {            //被選擇設(shè)置一下陰影            paint.setShadowLayer(20, 0, 0, Color.WHITE);        } else {            //沒選中去掉陰影            paint.clearShadowLayer();        }        canvas.drawPath(path, paint);

          接下來就是關(guān)于顏色的選擇問題了,寫一個(gè)獲得顏色的工具類,主要參數(shù)和構(gòu)造方法

              //存放顏色種類,并非真正的顏色    private int[] colorTypes;    //板塊接壤矩陣,1為接壤    private int[][] isBorder;    //準(zhǔn)備填充的顏色列表    private int[] colors;    //顏色多少種類    private int TYPE_SIZE ;    //總共有幾個(gè)板塊    private int plateCount;
          public ColorFillUtil(int[][] isBorder, int[] colors) throws Exception{ plateCount = isBorder.length; if (plateCount != isBorder[0].length) {//板塊相鄰關(guān)系必須是方陣,不能是矩陣 throw new Exception("colors's length must be equal to isBorder's length!"); } this.colors = colors; TYPE_SIZE = colors.length; this.isBorder = isBorder; }


          思路就是從第一個(gè)省份開始慢慢嘗試填充顏色,嘗試方法就是從可選的顏色種類中,依次填充進(jìn)去,然后再判斷是否和已經(jīng)填充的身份,是否有接壤并且同個(gè)顏色的,如果有就換一個(gè)顏色,如果最后每個(gè)顏色都嘗試了還是不行就說明上一個(gè)板塊填充有誤,要回退到上個(gè)板塊,如果上板塊還是不行再回退,最后直到每個(gè)板塊都設(shè)置好顏色,顏色種類如果小于4可能會(huì)填充失敗。詳細(xì)見后面代碼,以下是自定義省份的been

          public class ProviceItem {    private int index;    private Path path;    //省份顏色    private int drawColor;    //是否被點(diǎn)擊    private boolean isSelect;
          public ProviceItem(Path path) { this.path = path; }
          public void setDrawColor(int drawColor) { this.drawColor = drawColor; }

          public void setIndex(int index) { this.index = index; }
          public boolean isSelect() { return isSelect; }
          public void setSelect(boolean select) { isSelect = select; }
          public void drawItem(Canvas canvas, Paint paint) { paint.setStrokeWidth(1); paint.setColor(drawColor); paint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.drawPath(path, paint); if (isSelect) { //被選擇設(shè)置一下陰影 paint.setShadowLayer(20, 0, 0, Color.WHITE); } else { //沒選中去掉陰影 paint.clearShadowLayer(); } canvas.drawPath(path, paint); }
          public boolean isTouch(float x, float y) { //創(chuàng)建一個(gè)矩形 RectF rectF = new RectF(); //獲取到當(dāng)前省份的矩形邊界 path.computeBounds(rectF, true); //創(chuàng)建一個(gè)區(qū)域?qū)ο?/span> Region region = new Region(); //將path對(duì)象放入到Region區(qū)域?qū)ο笾?/span> region.setPath(path, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom)); //返回是否這個(gè)區(qū)域包含傳進(jìn)來的坐標(biāo) boolean resule = region.contains((int) x, (int) y); //無(wú)法通過代碼確定兩個(gè)省份是否接壤所以只能獲取下標(biāo),人工構(gòu)造省份相鄰矩陣,如果 // if (result) { // Log.d("ProviceItemIndex-----", index + ""); // } return result; }
          }


          自定義view的代碼

          public class MapView extends View {    private Paint paint;    private Context context;    //整個(gè)地圖所占用的矩形,在重新設(shè)配之前    private RectF totalRect;    private List<ProviceItem> proviceItems;    //繪制地圖的顏色    private int[] colorArray = new int[]{0xFF1383f2, 0xFFFFDC00, 0xFFFF3D33, 0xFF4ADE8C};    //適配比例    private float scale = 0;    int[] colors;    //中國(guó)省份接壤關(guān)系矩陣,劃分34個(gè)省份,自治區(qū),市和特別行政區(qū)等,但是多一個(gè)顏色表示國(guó)外的顏色項(xiàng)目中最后沒有用到    int[][] isBorder = {            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},            {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},            {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},            {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1},            {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1},
          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0},
          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},

          };
          public MapView(Context context) { super(context); }
          public MapView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context); }

          public MapView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
          private void init(Context context) { this.context = context; paint = new Paint(); paint.setAntiAlias(true); //開線程解析數(shù)據(jù) loadThread.start(); }
          @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); if (totalRect != null && width != 0) { //獲取到地圖的矩形的寬度 double mapWidth = totalRect.width(); //獲取到比例值 scale = (float) (width / mapWidth); //用寬度重新定義高度 heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (totalRect.height() * scale), MeasureSpec.EXACTLY); } super.onMeasure(widthMeasureSpec,heightMeasureSpec);
          }
          @Override protected void onDraw(Canvas canvas) { //如果省份數(shù)據(jù)還沒加載出來,實(shí)際縮放比例沒定義出來啥都不用干 if (proviceItems != null||scale==0) { super.onDraw(canvas); int tatalNum = proviceItems.size(); canvas.save(); canvas.scale(scale, scale); ProviceItem selsetProviceItem = null; // 先畫沒被選中的 for (int i = 0; i < tatalNum; i++) { if (!proviceItems.get(i).isSelect()) { proviceItems.get(i).drawItem(canvas, paint); } else { selsetProviceItem = proviceItems.get(i); } } //被選中的最后畫,因?yàn)楸贿x中的有陰影 if (selsetProviceItem != null) { selsetProviceItem.drawItem(canvas, paint); } } }
          private Thread loadThread = new Thread(new Runnable() { @Override public void run() { InputStream inputStream = context.getResources().openRawResource(R.raw.china); proviceItems = new ArrayList<>(); try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = null; builder = factory.newDocumentBuilder(); Document document = builder.parse(inputStream); Element rootElement = document.getDocumentElement(); NodeList items = rootElement.getElementsByTagName("path"); //定義一個(gè)不可能存在屏幕上的很右邊的點(diǎn)Integer.MAX_VALUE作為最左邊,同理定義一個(gè)不能存在屏幕上的很左邊的點(diǎn)-1作為為最左邊 //因?yàn)檠h(huán)每個(gè)省份的最左最右最上最下,左邊下標(biāo)只會(huì)越來越小 float left = Integer.MAX_VALUE; float right = -1; float top = Integer.MAX_VALUE; float bottom = -1; for (int i = 0; i < items.getLength(); i++) { Element element = (Element) items.item(i); String pathData = element.getAttribute("android:pathData"); Path path = PathParser.createPathFromPathData(pathData); ProviceItem proviceItem = new ProviceItem(path); //設(shè)置省份下標(biāo) //proviceItem.setIndex(i); proviceItems.add(proviceItem); RectF rectF = new RectF(); path.computeBounds(rectF, true); left = Math.min(left, rectF.left); right = Math.max(right, rectF.right); top = Math.min(top, rectF.top); bottom = Math.max(bottom, rectF.bottom); } //創(chuàng)建整個(gè)地圖 totalRect = new RectF(left, top, right, bottom); try { if (colors == null) { colors = new ColorFillUtil(isBorder, colorArray).getColors(); int totalNumber = proviceItems.size(); for (int i = 0; i < totalNumber; i++) { proviceItems.get(i).setDrawColor(colors[i]); } handler.sendEmptyMessage(0); } } catch (Exception e) { e.printStackTrace(); }
          } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } });

          private Handler handler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(@NonNull Message msg) { //返回主線程調(diào)用以下方法 //重新測(cè)量,調(diào)用onMeasure requestLayout(); //重新繪圖,系統(tǒng)調(diào)用onDraw invalidate(); } };
          @Override public boolean onTouchEvent(MotionEvent event) { //將當(dāng)前手指觸摸到位置傳過去 判斷當(dāng)前點(diǎn)擊的區(qū)域 handlerTouch(event.getX(), event.getY()); return super.onTouchEvent(event); }
          /** * 判斷區(qū)域 * * @param x * @param y */ private void handlerTouch(float x, float y) { //判空 if (proviceItems == null || proviceItems.size() == 0) { return; } for (ProviceItem proviceItem : proviceItems) { //入股點(diǎn)擊的是這個(gè)省份的范圍之內(nèi) 就把當(dāng)前省份的封裝對(duì)象繪制的方法 傳一個(gè)true proviceItem.setSelect(proviceItem.isTouch(x / scale, y / scale)); } postInvalidate(); }


          顏色選擇工具類

          /** * 板塊顏色填充工具 */public class ColorFillUtil {    //存放顏色種類,并非真正的顏色    private int[] colorTypes;    //板塊接壤矩陣,1為接壤    private int[][] isBorder;    //準(zhǔn)備填充的顏色列表    private int[] colors;    //顏色多少種類    private int TYPE_SIZE ;    //總共有幾個(gè)板塊    private int plateCount;
          public ColorFillUtil(int[][] isBorder, int[] colors) throws Exception{ plateCount = isBorder.length; if (plateCount != isBorder[0].length) {//板塊相鄰關(guān)系必須是方陣,不能是矩陣 throw new Exception("colors's length must be equal to isBorder's length!"); } this.colors = colors; TYPE_SIZE = colors.length; this.isBorder = isBorder; }

          /** * 獲取最后的結(jié)果 * @return */ public int[] getColors() {
          colorTypes = new int[plateCount]; int index = 0; int colorType = 0; while (index < plateCount) {
          if (setColor(index, colorType)) { //設(shè)置顏色種類暫時(shí)成功,接著下一個(gè),直到全部顏色設(shè)置完成,設(shè)置顏色種類從0開始嘗試 index++; colorType = 0; } else { //找不到合適的顏色要回退,上一個(gè)板塊修改顏色 index--; colorType = colorTypes[index] + 1; if (index == 0) //無(wú)法求解,可能是是顏色種類太少 return null; }
          } return getRealColors(); }
          /** * 返回真正的顏色列表 * @return */ private int[] getRealColors() { int[] result = new int[plateCount]; for (int i = 0; i < plateCount; i++) { result[i] = colors[colorTypes[i]]; } return result; }
          /** * 嘗試填充顏色 填充成功返回true * @param index 準(zhǔn)備填充的板塊下標(biāo) * @param colorType 準(zhǔn)備填充的顏色種類 * @return */ private boolean setColor(int index, int colorType) { if (colorType >= TYPE_SIZE) return false; while (colorType < TYPE_SIZE) { //是否可以設(shè)置顏色種類 boolean canSet = true; //循環(huán)判斷準(zhǔn)備填充的顏色與之前的顏色是否沖突 for (int i = 0; i < index; i++) { //isBorder[i][index] == 1 表示之前已經(jīng)填充的第i個(gè)板塊和準(zhǔn)備填充的板塊是接壤的 //colorType == colorTypes[i] 同時(shí)準(zhǔn)備填充的顏色種類又是一樣的,則準(zhǔn)備填充的顏色要改變,再重新嘗試填充 if (isBorder[i][index] == 1 && colorType == colorTypes[i]) {
          ++colorType; canSet = false; break; } } if (canSet) { colorTypes[index] = colorType; return true; } } //找不到合適的顏色,要回退 return false; }}


          部分資源文件
          https://pan.baidu.com/s/1Tgq84epnaFhmiEBotGeBgw

          瀏覽 54
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无码一区二区三区四区五区六区 | 男人的天堂地址 | 91精品无码人妻系列 | 中文字幕亚洲第一 | 爱爱视频不卡免费观看 |