onMeasure簡單方法 完美解決ListView與ScollView衝突問題!
近期做專案碰到ScrollView與Listview衝突的情況,檢視了網上一些解決listview和scollView的衝突的方法,最終選擇了重寫onMeasure的方法來解決這個問題。
在此對各種方法個人做一個總結評價。
主要的方法有四種:
1、手動設定ListView高度(比如把高度設定為200dp)
評價:特別簡單無腦,但是大大提高了程式碼的耦合性,比較適合“圖方便”的新手。
2、使用單個ListView的addHeaderView()方法(給listview設定頂部固定的一個view)
評價:比較簡便的方法,但是如果頂部佈局需要監聽滑動事件,也不可取。
3、使用LinearLayout取代ListView(重寫LinearLayout)
評價:完全可行,但是讓一個LinearLayout來實現Listview的功能真的覺得好奇怪啊。
4、重寫ListView的onMeasure()
評價:只需要寫幾行程式碼,輕鬆解決衝突問題。不僅降低程式碼耦合性,而且簡單。唯一的缺點,可能就是理解需要花比較多的時間。
最終效果:(左圖為改之前,右圖為改之後,原始碼在文章結尾)
主要實現程式碼:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
如上所示,使用expandSpec代替heightMeasureSpec。很容易理解,就是我們改變了的listview的高度獲取方式。
那麼MeasureSpec.makeMeasureSpec(int size,int mode)中的兩個引數又是什麼呢?
size:表示父佈局提供給你的大小參考
mode:表示規格,有EXACTLY、AT_MOST、UNSPECIFIED三種。
那麼我們程式碼中填的兩個值又分別表示什麼呢?
Integer.MAX_VALUE >> 2:表示父佈局給的參考的大小無限大。(listview無邊界)
MeasureSpec.AT_MOST:表示根據佈局的大小來確定listview最終的高度,也就是有多少內容就顯示多高。
(此處三種方式解釋引用郭霖前輩文章中部分內容)
1. EXACTLY
表示父檢視希望子檢視的大小應該是由specSize的值來決定的,系統預設會按照這個規則來設定子檢視的大小,開發人員當然也可以按照自己的意願設定成任意的大小。
2. AT_MOST
表示子檢視最多隻能是specSize中指定的大小,開發人員應該儘可能小得去設定這個檢視,並且保證不會超過specSize。系統預設會按照這個規則來設定子檢視的大小,開發人員當然也可以按照自己的意願設定成任意的大小。
3. UNSPECIFIED
表示開發人員可以將檢視按照自己的意願設定成任意的大小,沒有任何限制。這種情況比較少見,不太會用到。
倘若讀者還有疑問或者對View的繪製過程比較感興趣,可以參考郭霖前輩的部落格:
Android檢視繪製流程完全解析,帶你一步步深入瞭解View(二)
http://blog.csdn.net/guolin_blog/article/details/16330267
MainActivity:
package com.example.double2.listviewscollview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
public class MainActivity extends AppCompatActivity {
private MyListView mMyListView;
final private String[] test = {
"first", "second", "third", "fourth", "fifth",
"first", "second", "third", "fourth", "fifth"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initListView();
}
private void initListView() {
mMyListView = (MyListView) findViewById(R.id.lv_main);
mMyListView.setAdapter(
new ArrayAdapter<String>(
this, android.R.layout.simple_list_item_1, test));
}
}
package com.example.double2.listviewscollview;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
/**
* 專案名稱:ListViewScollView
* 建立人:Double2號
* 建立時間:2016/5/22 19:01
* 修改備註:
*/
public class MyListView extends ListView {
public MyListView(Context context) {
super(context);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//此處是程式碼的關鍵
//MeasureSpec.AT_MOST的意思就是wrap_content
//Integer.MAX_VALUE >> 2 是使用最大值的意思,也就表示的無邊界模式
//Integer.MAX_VALUE >> 2 此處表示是福佈局能夠給他提供的大小
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
activity_main:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<View
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@android:color/holo_green_light"
/>
<com.example.double2.listviewscollview.MyListView
android:id="@+id/lv_main"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</ScrollView>
相關文章
- 重寫ListView解決ListView內部ViewPaper滑動事件衝突問題View事件
- ScrollView 與ListView 滑動衝突解決View
- 解決Flutter的ListView巢狀ListView滑動衝突以及無限高度問題FlutterView巢狀
- 完美解決ScrollView巢狀ListView滑動衝突(有圖有真相)View巢狀
- JAR衝突問題的解決JAR
- git 解決版本衝突問題Git
- android NestedScrollView和ListView衝突問題AndroidView
- 如解決jquery與原生js衝突的問題jQueryJS
- GO 問題之多版本衝突解決Go
- iis和tomcat同時執行,完美解決80埠衝突問題Tomcat
- 使用SUI與JQuery衝突的解決方法UIjQuery
- 雙擊和單擊事件衝突解決方法事件
- jQuery.noConflict() 方法—— jquery庫與其他庫衝突的問題解決jQuery
- css命名衝突解決方法CSS
- HTML中兩個tabs導航衝突問題的解決方法HTML
- Maven中解決依賴衝突的問題Maven
- Android-GridView與ScrollView共用的衝突問題(類似ListView)AndroidView
- 用簡單的方法解決問題
- Android 解決BottomSheetDialog 拖曳衝突問題Android
- 簡單介紹Lombok使用@Tolerate實現衝突相容問題Lombok
- weblogic+axis jar包衝突問題的另一個解決方法WebJAR
- maven依賴衝突以及解決方法Maven
- 依賴衝突時的解決方法
- Git Worktree:解決分支依賴衝突的問題Git
- less中解決CSS3的calc衝突問題CSSS3
- Git 解決衝突Git
- git 解決衝突Git
- UITapGestureRecognizer與didSelectRowAtIndexPath衝突解決UIIndex
- listview+edittext完美解決方案View
- 解決預設方法衝突的規則
- hash解決衝突的方法優缺點
- linux下SVN衝突的解決方法Linux
- PPT中聲音“衝突”的解決方法
- Android Studio 包衝突解決方法Android
- Git:程式碼衝突常見解決方法Git
- 解決gerrit commit後pull發生衝突的問題MIT
- 關於 OkHttp 依賴衝突問題的解決過程HTTP
- 解決app中多語音出現的衝突問題APP