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>
相關文章
- android NestedScrollView和ListView衝突問題AndroidView
- 解決Flutter的ListView巢狀ListView滑動衝突以及無限高度問題FlutterView巢狀
- git 解決版本衝突問題Git
- JAR衝突問題的解決JAR
- iis和tomcat同時執行,完美解決80埠衝突問題Tomcat
- jQuery.noConflict() 方法—— jquery庫與其他庫衝突的問題解決jQuery
- Android 解決BottomSheetDialog 拖曳衝突問題Android
- GO 問題之多版本衝突解決Go
- hash衝突解決方法
- css命名衝突解決方法CSS
- HTML中兩個tabs導航衝突問題的解決方法HTML
- Git Worktree:解決分支依賴衝突的問題Git
- 簡單介紹Lombok使用@Tolerate實現衝突相容問題Lombok
- 依賴衝突時的解決方法
- maven依賴衝突以及解決方法Maven
- 解決gerrit commit後pull發生衝突的問題MIT
- git 解決衝突Git
- Git 解決衝突Git
- VMware無法啟動/VMware和wsl衝突問題/VMware與Hyper-V衝突問題
- 解決預設方法衝突的規則
- hash解決衝突的方法優缺點
- IIS子目錄web.config與主站衝突解決方法Web
- 程式衝突及其解決
- git pull 衝突解決Git
- Git衝突解決技巧Git
- 建立結算清單時提示衝突解決方案
- 徹底解決SLF4J的日誌衝突的問題
- ListView 與 RecyclerView 簡單對比View
- SVN解決衝突 記錄
- elmentui表單重置初始值問題與解決方法UI
- PtrClassicFrameLayout與viewpager橫向滑動衝突的問題Viewpager
- [奇技Y巧]解決程式快取鎖命名困難,命名衝突問題快取
- windows10玩遊戲鍵盤衝突怎麼辦 win10遊戲與鍵盤衝突解決方法Windows遊戲Win10
- wsl docker 和 ubuntu 衝突問題DockerUbuntu
- javamelody與swagger註解衝突JavaSwagger
- 解決 Laravel {{ }}與前端 VIM 模版引擎標記 衝突Laravel前端
- 常用的幾種專案衝突管理的解決方法
- 關於SVN update之後,引起衝突的解決方法
- git pull衝突的解決方案Git