系分项目总结--安卓前端UI一些有用的小技巧

安卓前端UI一些有用的小技巧

EditText的一键清除小x

效果图
很多软件在编辑框处都有一键清除的按钮,这里介绍一下其实现方式
xml文件添加如下,使得清除按钮位于EditText的最右方

<EditText
    android:id="@+id/login_username"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toBottomOf="@+id/login_username_text"
    android:gravity="center"
    android:hint="请输入用户名"/>

<Button
    android:id="@+id/login_username_clear"
    android:layout_width="25dp"
    android:layout_height="25dp"
    android:layout_marginRight="5dp"
    android:background="@mipmap/clear"
    android:visibility="invisible"
    app:layout_constraintBottom_toBottomOf="@id/login_username"
    app:layout_constraintRight_toRightOf="@id/login_username"
    app:layout_constraintTop_toTopOf="@id/login_username" />

然后就是在java文件onCreate函数中实现逻辑了,这里我们所用到的控件为TextWatcher

private EditText login_username;
private Button login_username_clear;
private TextWatcher login_username_watcher;

@Override
protected void onCreate(Bundle savedInstanceState) {
  	super.onCreate(savedInstanceState);
   	setContentView(R.layout.activity_login_register);

	login_username = (EditText)findViewById(R.id.login_username);
	login_username_clear = (Button)findViewById(R.id.login_username_clear);
	login_username.addTextChangedListener(login_username_watcher);

	login_username_watcher = new TextWatcher() {
    	public void onTextChanged(CharSequence s, int start, int before, int count) {}
    	public void beforeTextChanged(CharSequence s, int start, int count,int after) {}
    	public void afterTextChanged(Editable s) {
        	login_password.setText("");
        	if(s.toString().length()>0){
            	login_username_clear.setVisibility(View.VISIBLE);
        	}else{
            	login_username_clear.setVisibility(View.INVISIBLE);
        	}
  		}
	};
}

这样就实现了一键清除效果按钮了

自定义Toolbar实现logo和小组件

效果图
效果图
我使用Toolbar组件来实现了logo和APP名称的显示,同时还在右侧增加了小组件以便于功能拓展
首先要把原有的ActionBar删除,这里需要修改AndriodManifest文件

<activity
   	android:name=".MainPartActivity"
   	android:theme="@style/AppTheme" />
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- toolbar(actionbar)颜色 -->
    <item name="colorPrimary">@color/gray</item>
    <!-- 状态栏颜色 -->
    <item name="colorPrimaryDark">@android:color/darker_gray</item>
    <!-- 窗口的背景颜色 -->
    <item name="android:windowBackground">@color/white</item>
    <item name="actionOverflowMenuStyle">@style/MenuStyle</item>
</style>

删除了之后,就可以在xml文件中加入自定义的Toolbar了

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/colorPrimary"
    android:background="@color/Blue"
    app:navigationIcon="@mipmap/logo"
    app:popupTheme="@style/PopWindowBackgroundStyle"
    app:theme="@style/PopWindowStyle"
    app:title="易闲圈"
    app:titleTextColor="@color/black" />

其中的PopWindowBackgroundStyle如下

<style name="PopWindowStyle" parent="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    <!--字体和图标的颜色-->
    <item name="android:textColorPrimary">@color/black</item>
</style>

随后仍然是修改java文件

private Toolbar toolbar;
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_part);

	toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu, menu);
    return super.onCreateOptionsMenu(menu);
}

这里的main_menu就是自定义的右侧功能组文件,可以选择添加自己想要的功能,这里我定义了一个系统自带的搜索按钮和一个自定义的按钮

<?xml version="1.0" encoding="utf-8"?>
<menu android:name="menu1" xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/search"
        android:title="搜索框"
        android:icon="@mipmap/search"
        app:showAsAction="always"
        app:actionViewClass="android.support.v7.widget.SearchView" />

    <item
        android:icon="@mipmap/icon_add"
        app:showAsAction="always"
        android:title="添加"
        app:actionProviderClass="com.example.asus.earingmoney.adapter.PlusActionProvider"/>
</menu>

PlusActionProvider类用于自定义新按钮的功能

public class PlusActionProvider extends ActionProvider {
    /**
     * Creates a new instance.
     *
     * @param context Context for accessing resources.
     */
    private Context context;

    public PlusActionProvider(Context context) {
        super(context);
        this.context = context;
    }

    @Override
    public View onCreateActionView() {
        return null;
    }

    @Override
    public void onPrepareSubMenu(SubMenu subMenu) {
        subMenu.clear();
        subMenu.add(("新建跑腿任务"))
                .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem item) {
                        Intent intent = new Intent(getContext(),creat_errand_activity.class);
                        getContext().startActivity(intent);
                        return true;
                    }
                });
        subMenu.add(("新建问卷任务"))
                .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem item) {
                        Intent intent = new Intent(getContext(),createQuestionare.class);
                        getContext().startActivity(intent);
                        return true;
                    }
                });
    }

    @Override
    public boolean hasSubMenu() {
        return true;
    }
}

使用ViewPager和RadioGroup实现多页面滑动功能

效果图
三个界面支持点击下方按钮切换或滑动切换
首先要明白的是这三个界面都是在同一个activity下,其中的页面内容可以通过修改ViewPager中绑定的Fragment来实现,上方的Toolbar则可以通过如上一个话题的onCreateOptionsMenu函数来实现修改
xml文件修改如下

<android.support.v4.view.ViewPager
    android:id="@+id/fragment_vp"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:layout_constraintTop_toBottomOf="@+id/toolbar"
    app:layout_constraintBottom_toTopOf="@+id/tabs_rg"/>

<RadioGroup
    android:id="@+id/tabs_rg"
    android:layout_width="match_parent"
    android:layout_height="56dp"
    android:layout_alignParentBottom="true"
    android:background="#dcdcdc"
    android:orientation="horizontal"
    android:weightSum="3"
    app:layout_constraintBottom_toBottomOf="parent"
    android:paddingTop="5dp">

    <RadioButton
        android:id="@+id/main_tab"
        android:checked="true"
        android:text="首页"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_weight="1"
        android:button="@null"
        android:textColor="@color/radiobutton_textcolor"
        android:drawableTop="@drawable/tab_main_selector"
        android:gravity="center"/>

    <RadioButton
        android:id="@+id/tasks_tab"
        android:text="任务"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_weight="1"
        android:button="@null"
        android:textColor="@color/radiobutton_textcolor"
        android:drawableTop="@drawable/tab_tasks_selector"
        android:gravity="center"/>

    <RadioButton
        android:id="@+id/me_tab"
        android:text="我的"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_weight="1"
        android:button="@null"
        android:textColor="@color/radiobutton_textcolor"
        android:drawableTop="@drawable/tab_me_selector"
        android:gravity="center"/>
    
</RadioGroup>

activity页面如下

private ViewPager fragment_vp;
private RadioGroup tabs_rg;
private List<Fragment> fragments;
private FragmentPagerAdapter adapter;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_part);

        fragment_vp = findViewById(R.id.fragment_vp);
        tabs_rg = findViewById(R.id.tabs_rg);

        fragments = new ArrayList<>(3);
        fragments.add(MainFragment.newInstance("首页"));
        fragments.add(TasksFragment.newInstance("任务"));
        fragments.add(MeFragment.newInstance("我的"));


        adapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments);
        fragment_vp.setAdapter(adapter);

        fragment_vp.addOnPageChangeListener(mPageChangeListener);
        tabs_rg.setOnCheckedChangeListener(mOnCheckedChangeListener);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    fragment_vp.removeOnPageChangeListener(mPageChangeListener);
}

private ViewPager.OnPageChangeListener mPageChangeListener = new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        RadioButton radioButton = (RadioButton) tabs_rg.getChildAt(position);
        radioButton.setChecked(true);
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
};

private RadioGroup.OnCheckedChangeListener mOnCheckedChangeListener = new RadioGroup.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        for (int i = 0; i < group.getChildCount(); i++) {
            if (group.getChildAt(i).getId() == checkedId) {
                fragment_vp.setCurrentItem(i);
                if(headerUri != null)
                {
                    CircleImageView btn = findViewById(R.id.headerPic);
                    if(btn == null)
                    {
                        return;
                    }
                    btn.setImageURI(headerUri);
                }
                if(sex == Constants.FEMALE)
                {
                    ImageView sexImage = findViewById(R.id.sexImage);
                    if(sexImage == null)
                        return;
                    sexImage.setImageResource(R.mipmap.girl);
                }
                else
                {
                    ImageView sexImage = findViewById(R.id.sexImage);
                    if(sexImage == null)
                        return;
                    sexImage.setImageResource(R.mipmap.boy);
                }
                return;
            }
        }
    }
};

private class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> mList;

    public MyFragmentPagerAdapter(FragmentManager fm, List<Fragment> list) {
        super(fm);
        this.mList = list;
    }

    @Override
    public Fragment getItem(int position) {
        return this.mList == null ? null : this.mList.get(position);
    }

    @Override
    public int getCount() {
        return this.mList == null ? 0 : this.mList.size();
    }
}

最后再分别完成各个Fragment的内容就可以实现页面切换了

使用Spinner实现Listview的分类筛选和顺序显示功能

效果图
xml文件比较简单,由多个Spinner构成即可

<Spinner
    android:id="@+id/spinner1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1"/>

java文件如下,由于我是在Fragment中实现,所以会和在Activity中实现有所不同

public class MainFragment extends Fragment {

	private Spinner spinner1, spinner2, spinner3, spinner4;
    private List<Mission> missionslist = new ArrayList<Mission>();//missionslist为显示的内容,
    private List<Mission> totallist = new ArrayList<Mission>();   //totallist为所有mission内容,ques_list和err_list分别为问卷任务和跑腿任务
    private List<Mission> questionare_missionslist = new ArrayList<Mission>();
    private List<Mission> errand_missionslist = new ArrayList<Mission>();

	private String[] mItems1,mItems2,mItems3,mItems4;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.main_fragment, container, false);
        setHasOptionsMenu(true);

        spinner1 = rootView.findViewById(R.id.spinner1);
        spinner2 = rootView.findViewById(R.id.spinner2);
        spinner3 = rootView.findViewById(R.id.spinner3);
        spinner4 = rootView.findViewById(R.id.spinner4);
        mItems1 = getResources().getStringArray(R.array.spin1);
        mItems2 = getResources().getStringArray(R.array.spin2);
        mItems3 = getResources().getStringArray(R.array.spin3);
        mItems4 = getResources().getStringArray(R.array.spin4);
        ArrayAdapter<String> adapter1=new ArrayAdapter<String>(getActivity(),android.R.layout.simple_spinner_dropdown_item, mItems1);
        ArrayAdapter<String> adapter2=new ArrayAdapter<String>(getActivity(),android.R.layout.simple_spinner_dropdown_item, mItems2);
        ArrayAdapter<String> adapter3=new ArrayAdapter<String>(getActivity(),android.R.layout.simple_spinner_dropdown_item, mItems3);
        ArrayAdapter<String> adapter4=new ArrayAdapter<String>(getActivity(),android.R.layout.simple_spinner_dropdown_item, mItems4);
        adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        adapter3.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        adapter4.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        //绑定 Adapter到控件
        spinner1.setAdapter(adapter1);
        spinner2.setAdapter(adapter2);
        spinner3.setAdapter(adapter3);
        spinner4.setAdapter(adapter4);

		iniSpiner();
    }

    private void iniSpiner(){//用于排序、筛选

        spinner1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { //对问卷或跑腿任务进行筛选
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if(position == 0){
                    missionslist.clear();
                    missionslist.addAll(totallist);
                }
                else if(position == 1){
                    missionslist.clear();
                    missionslist.addAll(questionare_missionslist);
                }
                else{
                    missionslist.clear();
                    missionslist.addAll(errand_missionslist);
                }
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        spinner2.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){ //对酬劳进行排序

            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if(position == 0){
                    MissionsSortUtil.sortById(missionslist);
                }
                else if(position == 1){
                    MissionsSortUtil.sortByPriceUp(missionslist);
                }
                else {
                    MissionsSortUtil.sortByPriceDown(missionslist);
                }
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        spinner3.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){ //对截止时间进行排序

            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if(position == 0){
                    MissionsSortUtil.sortById(missionslist);
                }
                else if(position == 1){
                    MissionsSortUtil.sortByTimeUp(missionslist);
                }
                else {
                    MissionsSortUtil.sortByTimeDown(missionslist);
                }
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }
}

上面的iniSpiner函数仅是我所需要的功能,大家可根据自己的需求自行更改
还有上面的arrays文件则是用来显示spinner下拉后的内容

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="spin1">
        <item>所有类型</item>
        <item>问卷任务</item>
        <item>跑腿任务</item>
    </string-array>

    <string-array name="spin2">
        <item>任务酬劳</item>
        <item>升序</item>
        <item>降序</item>
    </string-array>

    <string-array name="spin3">
        <item>截止时间</item>
        <item>时间充裕</item>
        <item>时间急迫</item>
    </string-array>

    <string-array name="spin4">
        <item>tag</item>
        <item>tag1</item>
        <item>tag2</item>
    </string-array>

    <string-array name="missionOrTask">
        <item>我发布的</item>
        <item>我接受的</item>
    </string-array>

    <string-array name="completeness">
        <item>全部</item>
        <item>已完成</item>
        <item>未完成</item>
        <item>已过期</item>
    </string-array>
</resources>

上面代码中的几个MissionsSortUtil.sortBy函数也是我自己定义的排序函数,大家也可以根据自己Listview中的定义的属性来进行排序

public class MissionsSortUtil {

    static Comparator<Mission> missionComparatorById = new Comparator<Mission>() {
        @Override
        public int compare(Mission lhs, Mission rhs) {
            if(lhs.getMissionId() > rhs.getMissionId())
                return 1;
            return -1;       //注意此处不是0
        }
    };

    static Comparator<Mission> missionComparatorByPriceUp = new Comparator<Mission>() {
        @Override
        public int compare(Mission lhs, Mission rhs) {
            if(lhs.getMoney() < rhs.getMoney())
                return 1;
            return -1;       //注意此处不是0
        }
    };

    static Comparator<Mission> missionComparatorByPriceDown = new Comparator<Mission>() {
        @Override
        public int compare(Mission lhs, Mission rhs) {
            if(lhs.getMoney() > rhs.getMoney())
                return 1;
            return -1;       //注意此处不是0
        }
    };

    static Comparator<Mission> missionComparatorByTimeUp = new Comparator<Mission>() {
        @Override
        public int compare(Mission lhs, Mission rhs) {
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                if(sdf.parse(lhs.getDeadLine()).getTime() < sdf.parse(rhs.getDeadLine()).getTime())
                    return 1;
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return -1;
        }
    };

    static Comparator<Mission> missionComparatorByTimeDown = new Comparator<Mission>() {
        @Override
        public int compare(Mission lhs, Mission rhs) {
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                if(sdf.parse(lhs.getDeadLine()).getTime() > sdf.parse(rhs.getDeadLine()).getTime())
                    return 1;
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return -1;
        }
    };

    public static void sortById(List<Mission> missionsArray) {
        Collections.sort(missionsArray, missionComparatorById);
    }
    public static void sortByPriceUp(List<Mission> missionsArray) {
        Collections.sort(missionsArray, missionComparatorByPriceUp);
    }
    public static void sortByPriceDown(List<Mission> missionsArray) {
        Collections.sort(missionsArray, missionComparatorByPriceDown);
    }
    public static void sortByTimeUp(List<Mission> missionsArray) {
        Collections.sort(missionsArray, missionComparatorByTimeUp);
    }
    public static void sortByTimeDown(List<Mission> missionsArray) {
        Collections.sort(missionsArray, missionComparatorByTimeDown);
    }
}

使用SwipeRefreshLayout更新Listview

效果图

当我们使用Listview来显示我们从后台拿到的数据时,我们可能会想要有一个功能使得数据能够在想要的时候进行刷新,于是我就使用SwipeRefreshLayout实现了下拉刷新效果
xml文件更改如下

<android.support.v4.widget.SwipeRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:id="@+id/swipeLayout"
    app:layout_constraintTop_toBottomOf="@id/spinner_list_2"
    app:layout_constraintBottom_toBottomOf="parent">

    <ListView
        android:id = "@+id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp">
    </ListView>
</android.support.v4.widget.SwipeRefreshLayout>

java文件如下

    swipeRefreshLayout = rootView.findViewById(R.id.swipeLayout);
    swipeRefreshLayout.setSize(SwipeRefreshLayout.DEFAULT);
    swipeRefreshLayout.setProgressViewEndTarget(true, 200);

    swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            swipeRefreshLayout.setRefreshing(true);
            getMissions();
        }
    });

其中的setRefreshing函数即让它显示搜索时的转圈圈效果,这个效果需要手动关闭,即在getMissions函数结尾加上swipeRefreshLayout.setRefreshing(false);即可
以上就是我对这次大项目所总结出的几个界面UI实用的小技巧,希望能够帮助到大家

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值