在PreferenceAcitity中使用Fragement时避免额外的Left和RightPadding

本文探讨了Android 4.4系统下PreferenceActivity显示问题,即Activity的ActionBar部分出现额外的边框Padding现象。文章深入分析了PreferenceActivity及其Fragment的布局原理,并提供了解决方案,包括如何通过代码修改PreferenceFrameLayout的属性来移除边框。

On Android 4.4

遇到过这样的问题:

注意到,上面的ActionBar部分的左右各有48像素的padding。

 

要了解该问题的成因,要首先了解其结构:

  1. 该页面的Activity是一个PreferenceActivity,是个三级页面,是通过上一个PreferenceActivity调用startWithFragment启动的;
  2. 该页面的内容是放置了一个Fragment,该Fragment,实现了自己的ActionBar (ActionBar是来自Fragment而不是Acitivity)

我们通过hierarchyviewer看一下它的界面构成:

 

截图中的PreferenceFrameLayout就是这个关键类。

PreferenceAcitivity的布局文件是 frameworks/base/core/res/res/layout/preference_list_fragment.xml

但是,PreferenceFrameLayout类的风格却是由android内部的一个风格控制的:(frameworks/base/core/res/res/values/styles.xml)

<stylename="Widget.Holo.PreferenceFrameLayout">                                                                                                                                                        
    <itemname="android:borderTop">0dip</item>
    <itemname="android:borderBottom">@dimen/preference_fragment_padding_bottom</item>
    <itemname="android:borderLeft">?attr/preferenceFragmentPaddingSide</item>
    <itemname="android:borderRight">?attr/preferenceFragmentPaddingSide</item>
</style>

preferenceFragmentPaddingSide的值在不同平台值不同,在这里定义为16dip (16*3 = 48)

他通过默认风格引用的(frameworks/base/core/res/res/values/themes.xml)

<itemname="preferenceFrameLayoutStyle">@android:style/Widget.PreferenceFrameLayout</item>
这样,在默认情况下,PreferenceActivity都会带有边框Padding。

 

但是PreferenceFrameLayout还有一个特殊属性:layout_removeBorders。这个属性为true时,表示忽略padding。他对应的是PreferenceFrameLayout.LayoutParams.removeBorders 这个变量。

PreferenceFragment这个和PreferenceActivity匹配的Fragment,就具有该属性:(frameworks/base/core/res/res/layout/preference_list_fragment.xml)

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:background="@android:color/transparent"
    android:layout_removeBorders="true">
.....


因此,PreferenceFragment放到PreferenceActivity的时候,这个边框就没有了

不幸的时,以上所有的layout属性都是Private的,无法更改,因此,当我们的Fragment不是PreferenceFragment或者它的派生类的时候,就不能消除边框了。

 

不过,我们还有其他的解决方法,万幸的是PreferenceFrameLayout和PreferenceFrameLayout.LayoutParams都是Public的。因此,我们可以直接代码修改:

@Override
public View onInflateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
    View view = inflater.inflate(
        ....., container,false);
    if(container != null) {
        ViewGroup prefView = (ViewGroup)container.getParent();
        ViewGroup.LayoutParams layoutParams = (ViewGroup.LayoutParams)prefView.getLayoutParams();
        if(layoutParams instanceofPreferenceFrameLayout.LayoutParams) {
            ((PreferenceFrameLayout.LayoutParams)layoutParams).removeBorders =true;
        }
    }
    returnview;
}


在Fragment的onInflateView函数中强制修改removeBorders就可以达到这样的目的。

当然,需要正确找到PreferenceFrameLayout的第一个子View,修改该子View的LayoutParams才能生效,这需要根据不同的情况来分别对待。

Fragment是Android中的一种UI组件,它可以嵌入到Activity中,用于实现灵活的UI设计多屏幕适配。下面介绍一下Fragment的使用: 1. 创建Fragment类 首先需要创建一个继承自Fragment的子类,并实现其onCreateView()方法,该方法返回一个View对象,该View对象就是该Fragment的界面布局。 2. 在Activity中添加Fragment 在Activity的布局文件中添加一个FrameLayout容器,然后在Activity的代码中通过FragmentManagerFragmentTransaction来管理添加Fragment。例如: ```java MyFragment fragment = new MyFragment(); FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); transaction.add(R.id.fragment_container, fragment); transaction.commit(); ``` 其中,R.id.fragment_container是FrameLayout容器的id。 3. Fragment的生命周期 与Activity类似,Fragment也有自己的生命周期,包括onCreate、onAttach、onCreateView、onActivityCreated、onStart、onResume、onPause、onStop、onDestroyView、onDestroy、onDetach等方法。在Fragment的生命周期中,可以通过这些方法来处理一些与UI相关的逻辑。例如,可以在onCreateView方法中初始化布局,可以在onStart方法中开始某个操作,可以在onPause方法中停止某个操作等。 4. Fragment之间的通信 在Activity中,可以通过Intent来实现不同组件之间的通信,而在Fragment中,可以通过接口来实现Fragment之间的通信。具体来说,可以在一个Fragment中定义一个接口,并在另一个Fragment中实现该接口,从而实现两个Fragment之间的通信。例如: ```java public class MyFragment extends Fragment { public interface OnButtonClickListener { void onButtonClick(); } private OnButtonClickListener mListener; @Override public void onAttach(Context context) { super.onAttach(context); try { mListener = (OnButtonClickListener) context; } catch (ClassCastException e) { throw new ClassCastException(context.toString() + " must implement OnButtonClickListener"); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_layout, container, false); Button button = view.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mListener != null) { mListener.onButtonClick(); } } }); return view; } } public class AnotherFragment extends Fragment implements MyFragment.OnButtonClickListener { @Override public void onButtonClick() { // do something } } ``` 在上面的例子中,MyFragment定义了一个OnButtonClickListener接口,并在onAttach方法中将该接口的实现赋值给mListener变量。在MyFragment的界面布局中,当按钮被点击,会调用mListener的onButtonClick方法。另一个Fragment AnotherFragment实现了该接口,并在onButtonClick方法中对按钮点击事件进行处理。这样,就实现了两个Fragment之间的通信。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值