日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

介绍几个好用的android自定义控件

發布時間:2025/4/16 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 介绍几个好用的android自定义控件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先看效果圖,

看下這兩個界面,第一個中用到了一個自定義的FlowRadioGroup,支持復合子控件,自定義布局;

第二個界面中看到了輸入的數字 自動4位分割了吧;也用到了自定義的DivisionEditText控件。

下面直接看源碼FlowRadioGroup了;

1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.newgame.sdk.view; 18 19 import java.util.ArrayList; 20 21 import android.content.Context; 22 import android.content.res.TypedArray; 23 import android.util.AttributeSet; 24 import android.view.View; 25 import android.view.ViewGroup; 26 import android.widget.CompoundButton; 27 import android.widget.LinearLayout; 28 import android.widget.RadioButton; 29 30 /** 可以放多種布局控件,能找到radiobutton */ 31 public class FlowRadioGroup extends LinearLayout { 32 // holds the checked id; the selection is empty by default 33 private int mCheckedId = -1; 34 // tracks children radio buttons checked state 35 private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener; 36 // when true, mOnCheckedChangeListener discards events 37 private boolean mProtectFromCheckedChange = false; 38 private OnCheckedChangeListener mOnCheckedChangeListener; 39 private PassThroughHierarchyChangeListener mPassThroughListener; 40 41 // 存放當前的radioButton 42 private ArrayList<RadioButton> radioButtons; 43 44 public FlowRadioGroup(Context context) { 45 super(context); 46 setOrientation(VERTICAL); 47 init(); 48 } 49 50 public FlowRadioGroup(Context context, AttributeSet attrs) { 51 super(context, attrs); 52 init(); 53 } 54 55 private void init() { 56 mChildOnCheckedChangeListener = new CheckedStateTracker(); 57 mPassThroughListener = new PassThroughHierarchyChangeListener(); 58 super.setOnHierarchyChangeListener(mPassThroughListener); 59 radioButtons = new ArrayList<RadioButton>(); 60 } 61 62 @Override 63 public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) { 64 // the user listener is delegated to our pass-through listener 65 mPassThroughListener.mOnHierarchyChangeListener = listener; 66 } 67 68 @Override 69 protected void onFinishInflate() { 70 super.onFinishInflate(); 71 72 // checks the appropriate radio button as requested in the XML file 73 if (mCheckedId != -1) { 74 mProtectFromCheckedChange = true; 75 setCheckedStateForView(mCheckedId, true); 76 mProtectFromCheckedChange = false; 77 setCheckedId(mCheckedId); 78 } 79 } 80 81 @Override 82 public void addView(View child, int index, ViewGroup.LayoutParams params) { 83 if (child instanceof RadioButton) { 84 final RadioButton button = (RadioButton) child; 85 radioButtons.add(button); 86 87 if (button.isChecked()) { 88 mProtectFromCheckedChange = true; 89 if (mCheckedId != -1) { 90 setCheckedStateForView(mCheckedId, false); 91 } 92 mProtectFromCheckedChange = false; 93 setCheckedId(button.getId()); 94 } 95 } else if (child instanceof ViewGroup) {// 如果是復合控件 96 // 遍歷復合控件 97 ViewGroup vg = ((ViewGroup) child); 98 setCheckedView(vg); 99 } 100 101 super.addView(child, index, params); 102 } 103 104 /** 查找復合控件并設置radiobutton */ 105 private void setCheckedView(ViewGroup vg) { 106 int len = vg.getChildCount(); 107 for (int i = 0; i < len; i++) { 108 if (vg.getChildAt(i) instanceof RadioButton) {// 如果找到了,就設置check狀態 109 final RadioButton button = (RadioButton) vg.getChildAt(i); 110 // 添加到容器 111 radioButtons.add(button); 112 if (button.isChecked()) { 113 mProtectFromCheckedChange = true; 114 if (mCheckedId != -1) { 115 setCheckedStateForView(mCheckedId, false); 116 } 117 mProtectFromCheckedChange = false; 118 setCheckedId(button.getId()); 119 } 120 } else if (vg.getChildAt(i) instanceof ViewGroup) {// 迭代查找并設置 121 ViewGroup childVg = (ViewGroup) vg.getChildAt(i); 122 setCheckedView(childVg); 123 } 124 } 125 } 126 127 /** 查找復合控件并設置id */ 128 private void setCheckedId(ViewGroup vg) { 129 int len = vg.getChildCount(); 130 for (int i = 0; i < len; i++) { 131 if (vg.getChildAt(i) instanceof RadioButton) {// 如果找到了,就設置check狀態 132 final RadioButton button = (RadioButton) vg.getChildAt(i); 133 int id = button.getId(); 134 // generates an id if it's missing 135 if (id == View.NO_ID) { 136 id = button.hashCode(); 137 button.setId(id); 138 } 139 button.setOnCheckedChangeListener(mChildOnCheckedChangeListener); 140 } else if (vg.getChildAt(i) instanceof ViewGroup) {// 迭代查找并設置 141 ViewGroup childVg = (ViewGroup) vg.getChildAt(i); 142 setCheckedId(childVg); 143 } 144 } 145 } 146 147 /** 查找radioButton控件 */ 148 public RadioButton findRadioButton(ViewGroup group) { 149 RadioButton resBtn = null; 150 int len = group.getChildCount(); 151 for (int i = 0; i < len; i++) { 152 if (group.getChildAt(i) instanceof RadioButton) { 153 resBtn = (RadioButton) group.getChildAt(i); 154 } else if (group.getChildAt(i) instanceof ViewGroup) { 155 resBtn = findRadioButton((ViewGroup) group.getChildAt(i)); 156 findRadioButton((ViewGroup) group.getChildAt(i)); 157 break; 158 } 159 } 160 return resBtn; 161 } 162 163 /** 返回當前radiobutton控件的count */ 164 public int getRadioButtonCount() { 165 return radioButtons.size(); 166 } 167 168 /** 返回當前index的radio */ 169 public RadioButton getRadioButton(int index) { 170 return radioButtons.get(index); 171 } 172 173 /** 174 * <p> 175 * Sets the selection to the radio button whose identifier is passed in 176 * parameter. Using -1 as the selection identifier clears the selection; 177 * such an operation is equivalent to invoking {@link #clearCheck()}. 178 * </p> 179 * 180 * @param id 181 * the unique id of the radio button to select in this group 182 * 183 * @see #getCheckedRadioButtonId() 184 * @see #clearCheck() 185 */ 186 public void check(int id) { 187 // don't even bother 188 if (id != -1 && (id == mCheckedId)) { 189 return; 190 } 191 192 if (mCheckedId != -1) { 193 setCheckedStateForView(mCheckedId, false); 194 } 195 196 if (id != -1) { 197 setCheckedStateForView(id, true); 198 } 199 200 setCheckedId(id); 201 } 202 203 private void setCheckedId(int id) { 204 mCheckedId = id; 205 if (mOnCheckedChangeListener != null) { 206 mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId); 207 } 208 } 209 210 private void setCheckedStateForView(int viewId, boolean checked) { 211 View checkedView = findViewById(viewId); 212 if (checkedView != null && checkedView instanceof RadioButton) { 213 ((RadioButton) checkedView).setChecked(checked); 214 } 215 } 216 217 /** 218 * <p> 219 * Returns the identifier of the selected radio button in this group. Upon 220 * empty selection, the returned value is -1. 221 * </p> 222 * 223 * @return the unique id of the selected radio button in this group 224 * 225 * @see #check(int) 226 * @see #clearCheck() 227 */ 228 public int getCheckedRadioButtonId() { 229 return mCheckedId; 230 } 231 232 /** 233 * <p> 234 * Clears the selection. When the selection is cleared, no radio button in 235 * this group is selected and {@link #getCheckedRadioButtonId()} returns 236 * null. 237 * </p> 238 * 239 * @see #check(int) 240 * @see #getCheckedRadioButtonId() 241 */ 242 public void clearCheck() { 243 check(-1); 244 } 245 246 /** 247 * <p> 248 * Register a callback to be invoked when the checked radio button changes 249 * in this group. 250 * </p> 251 * 252 * @param listener 253 * the callback to call on checked state change 254 */ 255 public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { 256 mOnCheckedChangeListener = listener; 257 } 258 259 /** 260 * {@inheritDoc} 261 */ 262 @Override 263 public LayoutParams generateLayoutParams(AttributeSet attrs) { 264 return new FlowRadioGroup.LayoutParams(getContext(), attrs); 265 } 266 267 /** 268 * {@inheritDoc} 269 */ 270 @Override 271 protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 272 return p instanceof FlowRadioGroup.LayoutParams; 273 } 274 275 @Override 276 protected LinearLayout.LayoutParams generateDefaultLayoutParams() { 277 return new LayoutParams(LayoutParams.WRAP_CONTENT, 278 LayoutParams.WRAP_CONTENT); 279 } 280 281 /** 282 * <p> 283 * This set of layout parameters defaults the width and the height of the 284 * children to {@link #WRAP_CONTENT} when they are not specified in the XML 285 * file. Otherwise, this class ussed the value read from the XML file. 286 * </p> 287 * 288 * <p> 289 * See {@link android.R.styleable#LinearLayout_Layout LinearLayout 290 * Attributes} for a list of all child view attributes that this class 291 * supports. 292 * </p> 293 * 294 */ 295 public static class LayoutParams extends LinearLayout.LayoutParams { 296 /** 297 * {@inheritDoc} 298 */ 299 public LayoutParams(Context c, AttributeSet attrs) { 300 super(c, attrs); 301 } 302 303 /** 304 * {@inheritDoc} 305 */ 306 public LayoutParams(int w, int h) { 307 super(w, h); 308 } 309 310 /** 311 * {@inheritDoc} 312 */ 313 public LayoutParams(int w, int h, float initWeight) { 314 super(w, h, initWeight); 315 } 316 317 /** 318 * {@inheritDoc} 319 */ 320 public LayoutParams(ViewGroup.LayoutParams p) { 321 super(p); 322 } 323 324 /** 325 * {@inheritDoc} 326 */ 327 public LayoutParams(MarginLayoutParams source) { 328 super(source); 329 } 330 331 /** 332 * <p> 333 * Fixes the child's width to 334 * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the 335 * child's height to 336 * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} when not 337 * specified in the XML file. 338 * </p> 339 * 340 * @param a 341 * the styled attributes set 342 * @param widthAttr 343 * the width attribute to fetch 344 * @param heightAttr 345 * the height attribute to fetch 346 */ 347 @Override 348 protected void setBaseAttributes(TypedArray a, int widthAttr, 349 int heightAttr) { 350 351 if (a.hasValue(widthAttr)) { 352 width = a.getLayoutDimension(widthAttr, "layout_width"); 353 } else { 354 width = WRAP_CONTENT; 355 } 356 357 if (a.hasValue(heightAttr)) { 358 height = a.getLayoutDimension(heightAttr, "layout_height"); 359 } else { 360 height = WRAP_CONTENT; 361 } 362 } 363 } 364 365 /** 366 * <p> 367 * Interface definition for a callback to be invoked when the checked radio 368 * button changed in this group. 369 * </p> 370 */ 371 public interface OnCheckedChangeListener { 372 /** 373 * <p> 374 * Called when the checked radio button has changed. When the selection 375 * is cleared, checkedId is -1. 376 * </p> 377 * 378 * @param group 379 * the group in which the checked radio button has changed 380 * @param checkedId 381 * the unique identifier of the newly checked radio button 382 */ 383 public void onCheckedChanged(FlowRadioGroup group, int checkedId); 384 } 385 386 private class CheckedStateTracker implements 387 CompoundButton.OnCheckedChangeListener { 388 public void onCheckedChanged(CompoundButton buttonView, 389 boolean isChecked) { 390 // prevents from infinite recursion 391 if (mProtectFromCheckedChange) { 392 return; 393 } 394 395 mProtectFromCheckedChange = true; 396 if (mCheckedId != -1) { 397 setCheckedStateForView(mCheckedId, false); 398 } 399 mProtectFromCheckedChange = false; 400 401 int id = buttonView.getId(); 402 setCheckedId(id); 403 } 404 } 405 406 /** 407 * <p> 408 * A pass-through listener acts upon the events and dispatches them to 409 * another listener. This allows the table layout to set its own internal 410 * hierarchy change listener without preventing the user to setup his. 411 * </p> 412 */ 413 private class PassThroughHierarchyChangeListener implements 414 ViewGroup.OnHierarchyChangeListener { 415 private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener; 416 417 public void onChildViewAdded(View parent, View child) { 418 if (parent == FlowRadioGroup.this && child instanceof RadioButton) { 419 int id = child.getId(); 420 // generates an id if it's missing 421 if (id == View.NO_ID) { 422 id = child.hashCode(); 423 child.setId(id); 424 } 425 ((RadioButton) child) 426 .setOnCheckedChangeListener(mChildOnCheckedChangeListener); 427 } else if (parent == FlowRadioGroup.this 428 && child instanceof ViewGroup) {// 如果是復合控件 429 // 查找并設置id 430 setCheckedId((ViewGroup) child); 431 } 432 433 if (mOnHierarchyChangeListener != null) { 434 mOnHierarchyChangeListener.onChildViewAdded(parent, child); 435 } 436 } 437 438 public void onChildViewRemoved(View parent, View child) { 439 if (parent == FlowRadioGroup.this && child instanceof RadioButton) { 440 ((RadioButton) child).setOnCheckedChangeListener(null); 441 } else if (parent == FlowRadioGroup.this 442 && child instanceof ViewGroup) { 443 findRadioButton((ViewGroup) child).setOnCheckedChangeListener( 444 null); 445 } 446 if (mOnHierarchyChangeListener != null) { 447 mOnHierarchyChangeListener.onChildViewRemoved(parent, child); 448 } 449 } 450 } 451 }

簡單講解下我的實現:

1)在addview方法中,加上判斷,當前子控件是否為viewgroup類型

@Overridepublic void addView(View child, int index, ViewGroup.LayoutParams params) {if (child instanceof RadioButton) {final RadioButton button = (RadioButton) child;radioButtons.add(button);//將找到的控件添加到集合中if (button.isChecked()) {mProtectFromCheckedChange = true;if (mCheckedId != -1) {setCheckedStateForView(mCheckedId, false);}mProtectFromCheckedChange = false;setCheckedId(button.getId());}} else if (child instanceof ViewGroup) {// 如果是復合控件// 遍歷復合控件ViewGroup vg = ((ViewGroup) child);setCheckedView(vg);}super.addView(child, index, params);}/** 查找復合控件并設置radiobutton */private void setCheckedView(ViewGroup vg) {int len = vg.getChildCount();for (int i = 0; i < len; i++) {if (vg.getChildAt(i) instanceof RadioButton) {// 如果找到了,就設置check狀態final RadioButton button = (RadioButton) vg.getChildAt(i);// 添加到容器 radioButtons.add(button);if (button.isChecked()) {mProtectFromCheckedChange = true;if (mCheckedId != -1) {setCheckedStateForView(mCheckedId, false);}mProtectFromCheckedChange = false;setCheckedId(button.getId());}} else if (vg.getChildAt(i) instanceof ViewGroup) {// 迭代查找并設置ViewGroup childVg = (ViewGroup) vg.getChildAt(i);setCheckedView(childVg);}}}

?

2)定義一個數組存放當前所有查到到的radiobutton;

3)在onChildViewAdded方法中,判斷新添加的子控件是否為viewgroup類型

1 2 3 4 5 else?if?(parent == FlowRadioGroup.this ????????????????????&& child?instanceof?ViewGroup) {// 如果是復合控件 ????????????????// 查找并設置id ????????????????setCheckedId((ViewGroup) child); ????????????}

  

/** 查找復合控件并設置id */private void setCheckedId(ViewGroup vg) {int len = vg.getChildCount();for (int i = 0; i < len; i++) {if (vg.getChildAt(i) instanceof RadioButton) {// 如果找到了,就設置check狀態final RadioButton button = (RadioButton) vg.getChildAt(i);int id = button.getId();// generates an id if it's missingif (id == View.NO_ID) {id = button.hashCode();button.setId(id);}button.setOnCheckedChangeListener(mChildOnCheckedChangeListener);} else if (vg.getChildAt(i) instanceof ViewGroup) {// 迭代查找并設置ViewGroup childVg = (ViewGroup) vg.getChildAt(i);setCheckedId(childVg);}}}

?

下面是DivisionEditText的源碼;

1 package com.newgame.sdk.view; 2 3 import android.content.Context; 4 import android.text.Editable; 5 import android.text.TextWatcher; 6 import android.util.AttributeSet; 7 import android.view.View; 8 import android.widget.EditText; 9 10 /** 11 * 分割輸入框 12 * 13 * @author Administrator 14 * 15 */ 16 public class DivisionEditText extends EditText { 17 18 /* 每組的長度 */ 19 private Integer eachLength = 4; 20 /* 分隔符 */ 21 private String delimiter = " "; 22 23 private String text = ""; 24 25 public DivisionEditText(Context context) { 26 super(context); 27 init(); 28 } 29 30 public DivisionEditText(Context context, AttributeSet attrs) { 31 super(context, attrs); 32 init(); 33 34 } 35 36 public DivisionEditText(Context context, AttributeSet attrs, int defStyle) { 37 super(context, attrs, defStyle); 38 init(); 39 } 40 41 /** 42 * 初始化 43 */ 44 public void init() { 45 46 // 內容變化監聽 47 this.addTextChangedListener(new DivisionTextWatcher()); 48 // 獲取焦點監聽 49 this.setOnFocusChangeListener(new DivisionFocusChangeListener()); 50 } 51 52 /** 53 * 文本監聽 54 * 55 * @author Administrator 56 * 57 */ 58 private class DivisionTextWatcher implements TextWatcher { 59 60 @Override 61 public void afterTextChanged(Editable s) { 62 } 63 64 @Override 65 public void beforeTextChanged(CharSequence s, int start, int count, 66 int after) { 67 } 68 69 @Override 70 public void onTextChanged(CharSequence s, int start, int before, 71 int count) { 72 // 統計個數 73 int len = s.length(); 74 if (len < eachLength)// 長度小于要求的數 75 return; 76 if (count > 1) { 77 return; 78 } 79 // 如果包含空格,就清除 80 char[] chars = s.toString().replace(" ", "").toCharArray(); 81 len = chars.length; 82 // 每4個分組,加上空格組合成新的字符串 83 StringBuffer sb = new StringBuffer(); 84 for (int i = 0; i < len; i++) { 85 if (i % eachLength == 0 && i != 0)// 每次遍歷到4的倍數,就添加一個空格 86 { 87 sb.append(" "); 88 sb.append(chars[i]);// 添加字符 89 } else { 90 sb.append(chars[i]);// 添加字符 91 } 92 } 93 // 設置新的字符到文本 94 // System.out.println("*************" + sb.toString()); 95 text = sb.toString(); 96 setText(text); 97 setSelection(text.length()); 98 } 99 } 100 101 /** 102 * 獲取焦點監聽 103 * 104 * @author Administrator 105 * 106 */ 107 private class DivisionFocusChangeListener implements OnFocusChangeListener { 108 109 @Override 110 public void onFocusChange(View v, boolean hasFocus) { 111 if (hasFocus) { 112 // 設置焦點 113 setSelection(getText().toString().length()); 114 } 115 } 116 } 117 118 /** 得到每組個數 */ 119 public Integer getEachLength() { 120 return eachLength; 121 } 122 123 /** 設置每組個數 */ 124 public void setEachLength(Integer eachLength) { 125 this.eachLength = eachLength; 126 } 127 128 /** 得到間隔符 */ 129 public String getDelimiter() { 130 return delimiter; 131 } 132 133 /** 設置間隔符 */ 134 public void setDelimiter(String delimiter) { 135 this.delimiter = delimiter; 136 } 137 138 }

上面代碼實現邏輯:在TextWatcher的onTextChanged方法中判斷當前輸入的字符,然后沒4位添加一個空格,組成新的字符

@Overridepublic void onTextChanged(CharSequence s, int start, int before,int count) {// 統計個數int len = s.length();if (len < eachLength)// 長度小于要求的數return;if (count > 1) {// 設置新字符串的時候,直接返回return;}// 如果包含空格,就清除char[] chars = s.toString().replace(" ", "").toCharArray();len = chars.length;// 每4個分組,加上空格組合成新的字符串StringBuffer sb = new StringBuffer();for (int i = 0; i < len; i++) {if (i % eachLength == 0 && i != 0)// 每次遍歷到4的倍數,就添加一個空格 {sb.append(" ");sb.append(chars[i]);// 添加字符} else {sb.append(chars[i]);// 添加字符 }}// 設置新的字符到文本// System.out.println("*************" + sb.toString());text = sb.toString();setText(text);setSelection(text.length());}

?

還有其他兩個自定義控件也在項目中,這里界面沒體現出來,我已經放在項目中了;

歡迎大家找出代碼中的存在bug!!!!

最后附上代碼下載地址:http://www.eoeandroid.com/forum.php?mod=attachment&aid=MTIwMDM1fDM5NTYzZjQ3fDEzOTY0Mjc4NDF8NzU4MzI1fDMyODQyNw%3D%3D

總結

以上是生活随笔為你收集整理的介绍几个好用的android自定义控件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲精品www| 久久久久久国产免费a片 | 极品美女扒开粉嫩小泬 | 亚洲国产日韩a在线播放性色 | 国产精品久久久久久久久毛片 | 老色批影视 | 色老汉av一区二区三区 | 在线看网站 | 欧美黄色大片免费观看 | av男人的天堂网 | 日韩大胆人体 | 国产丝袜视频在线观看 | 伊人午夜| 国产中年熟女高潮大集合 | 美女扒开尿口给男人看 | 日韩av综合在线 | 午夜草逼 | 专干老肥女人88av | 国产精品视频播放 | 伊人春色在线观看 | 欧美18av | 国产微拍一区 | 在线免费观看日韩av | 小视频在线免费观看 | 山外人精品影院 | 99这里 | 人妻丰满熟妇av无码区免 | 人妻无码中文字幕免费视频蜜桃 | 亚洲av成人精品日韩在线播放 | 免费人成又黄又爽又色 | 天天插视频 | 青草91 | 人妻互换免费中文字幕 | 91尤物视频在线观看 | 国产精品免费一区二区三区四区 | 国产情侣露脸自拍 | 宅男av在线 | 久久久777 | 男女激情免费网站 | 久久动态图 | 狼人久久| 在线观看中文 | 国产成人av无码精品 | 一区二区三区美女 | 精品国精品国产 | 人人入人人| 午夜在线小视频 | 五月天视频网 | 6080午夜伦理 | 亚洲乱色熟女一区二区三区 | 欧美女优一区 | 四虎色 | 91深夜视频 | 亚洲第一页中文字幕 | 午夜黄色网址 | 亚洲精品911| 成人青青草 | 91麻豆精品国产91久久久久久 | 亚洲精品一区二区三区精华液 | 深夜在线免费视频 | 欧美性免费 | 91高潮大合集爽到抽搐 | 欧美精品一区二区三区久久久竹菊 | 玩弄丰满少妇xxxxx性多毛 | 亚洲欧美另类国产 | 免费在线观看av | 国内av在线播放 | 精品日韩在线观看 | 激情五月婷婷丁香 | 韩日视频在线观看 | 琪琪秋霞午夜被窝电影网 | 日韩美女中文字幕 | 国产高潮呻吟久久 | 亚洲成人一级 | 欧美一卡二卡三卡 | 日韩一区二区影视 | 捆绑凌虐一区二区三区 | 超碰超碰在线 | 亚洲人成人网 | 国产成人精品无码播放 | 91九色蝌蚪视频 | 原神女裸体看个够无遮挡 | 久久精品日韩 | 都市激情自拍 | 国产日产亚洲系列最新 | 日韩精品中文字 | 久久亚洲AV无码 | 久久综合一区二区 | 桃色视频网 | 久久高清 | 有码av在线| 欧美 亚洲 激情 一区 | 色吧综合 | 黄色av网站在线 | 免费视频91| 无码人妻精品一区二区三区在线 | 国产爆乳无码一区二区麻豆 | 精品国产一区二区三区性色av | 亚洲国产欧洲 |