Android实现基于Fragment的多账号下拉列表实现Demo

Android实现基于Fragment的多账号下拉列表实现Demo

项目要求:

做出如QQ登录一样的多账号下拉列表,Android里的Spinner虽然可以简单实现出下拉,但是目标是要在下拉的同时还可以在文本框里输入内容,且还可以选择删除相应记录,接下来就用EdiText、PopupWindow、ListView及Adapter实现下

效果图:

 

1.先创建好一个带EditText和一个下标图标的Fragment


布局如下:

【文件名:fragment_1.xml】

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/rl_1"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="148dp">
        <EditText
            android:id="@+id/et_1"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"/>

        <ImageView
            android:id="@+id/img_1"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:src="@drawable/down"
            android:layout_alignParentTop="true"
            android:layout_alignParentEnd="true"/>

    </RelativeLayout>

    <TextView
        android:text="DEMO"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="127dp"
        android:id="@+id/textView2"
        android:layout_below="@+id/rl_1"
        android:layout_centerHorizontal="true"/>

</RelativeLayout>

2.创建好适配器所需布局文件

【文件名:select_options.xml】

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:gravity="center_horizontal"
    >
    <ListView android:id="@+id/list" android:layout_width="fill_parent"
              android:layout_height="wrap_content" android:cacheColorHint="#00000000">
    </ListView>
</LinearLayout>
【文件名:select_option_item.xml】

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:background="#ffffff"
    >

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:minHeight="40dp"
        >

        <ImageView
            android:id="@+id/delImage"
            android:layout_width="20dp"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="10dp"
            android:src="@drawable/close"
            android:textSize="18sp"/>

        <TextView
            android:id="@+id/item_text"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_toLeftOf="@id/delImage"
            android:paddingLeft="5dp"></TextView>
    </RelativeLayout>
</LinearLayout>

3.创建适配器
其中会内置sendMessage方法,以便通知到Fragment层修改文本框内容为选中值

【文件名:OptionsAdapter.java】

package com.king.popupwindowtest;

/**
 * Created by KingLee on 2018/5/5.
 */

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;

public class OptionsAdapter extends BaseAdapter {

    private ArrayList<String> list = new ArrayList<String>();
    private Activity activity = null;
    private Handler handler;

    /**
     * 自定义构造方法
     * @param activity
     * @param handler
     * @param list
     */
    public OptionsAdapter(Activity activity,Handler handler,ArrayList<String> list){
        this.activity = activity;
        this.handler = handler;
        this.list = list;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            holder = new ViewHolder();
            //下拉项布局
            convertView = LayoutInflater.from(activity).inflate(R.layout.select_option_item, null);
            holder.textView = (TextView) convertView.findViewById(R.id.item_text);
            holder.imageView = (ImageView) convertView.findViewById(R.id.delImage);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.textView.setText(list.get(position));

        //为下拉框选项文字部分设置事件,最终效果是点击将其文字填充到文本框
        holder.textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = new Message();
                Bundle data = new Bundle();
                //设置选中索引
                data.putInt("selIndex", position);
                msg.setData(data);
                msg.what = 3;
                //发出消息
                handler.sendMessage(msg);
            }
        });

        //为下拉框选项删除图标部分设置事件,最终效果是点击将该选项删除
        holder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = new Message();
                Bundle data = new Bundle();
                //设置删除索引
                data.putInt("delIndex", position);
                msg.setData(data);
                msg.what = 4;
                //发出消息
                handler.sendMessage(msg);
            }
        });

        return convertView;
    }

}

class ViewHolder {
    TextView textView;
    ImageView imageView;
}

3.重写Fragment
需继承Callback接口,收到适配器发送的内容并进行UI更改。
此文件需要注意的是在Fragment的onWindowFocusChanged调用方法

【文件名:FragmentDemo.java】

package com.king.popupwindowtest;

import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;

import java.util.ArrayList;

import static com.king.popupwindowtest.R.id.rl_1;

/**
 * Created by KingLee on 2018/5/5.
 */

public class FragmentDemo extends Fragment implements Handler.Callback {

    private View view;
    private ImageView img_1;
    private EditText et_1;

    //控制列表开关
    private String multi_sign = "0";
    //PopupWindow对象
    private PopupWindow selectPopupWindow = null;
    //自定义Adapter
    private OptionsAdapter optionsAdapter = null;
    //下拉框选项数据源
    private ArrayList Select_datas = new ArrayList();
    //下拉框依附组件
    private RelativeLayout select_parent;
    //下拉框依附组件宽度,也将作为下拉框的宽度
    private int pwidth;
    //展示所有下拉选项的ListView
    private ListView select_listView = null;
    //用来处理选中或者删除下拉项消息
    private Handler select_handler;
    //是否初始化完成标志
    private boolean select_flag = false;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_1, container, false);
        bindViews();

        setMultiAccount();
        return view;
    }

    private void setMultiAccount() {
        //Fragment调起OnWindowFocusChangeListener写法
        view.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver
                .OnWindowFocusChangeListener() {
            @Override
            public void onWindowFocusChanged(boolean hasFocus) {
                getActivity().onWindowFocusChanged(hasFocus);
                if (getActivity() != null) {
                    if (multi_sign.equals("0")) {
                        getActivity().runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                img_1.setImageDrawable(getResources().getDrawable(R.drawable.down));
                            }
                        });
                        multi_sign = "1";
                    } else {
                        getActivity().runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                img_1.setImageDrawable(getResources().getDrawable(R.drawable.up));
                            }
                        });
                        multi_sign = "0";
                    }
                }
                while (!select_flag) {
                    initWedget();
                    select_flag = true;
                }
            }
        });
    }

    /**
     * 初始化填充Adapter所用List数据
     */
    private void initDatas() {
        Select_datas.clear();
        Select_datas.add("111111");
        Select_datas.add("222222");
        Select_datas.add("333333");
    }

    private void initWedget() {
        //初始化Handler,用来处理消息
        select_handler = new Handler(FragmentDemo.this);

        //初始化界面组件
        select_parent = (RelativeLayout) view.findViewById(rl_1);

        //获取下拉框依附的组件宽度
        int width = select_parent.getWidth();
        pwidth = width;

        //设置点击下拉箭头图片事件,点击弹出PopupWindow浮动下拉框
        img_1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (select_flag) {
                    //显示PopupWindow窗口
                    popupWindwShowing();
                }
            }
        });
        initPopuWindow();
    }

    /**
     * 显示PopupWindow窗口
     *
     * @param
     */
    public void popupWindwShowing() {
        //将selectPopupWindow作为parent的下拉框显示,并指定selectPopupWindow在Y方向上向上偏移3pix,
        //这是为了防止下拉框与文本框之间产生缝隙,影响界面美化
        //(是否会产生缝隙,及产生缝隙的大小,可能会根据机型、Android系统版本不同而异吧,不太清楚)
        selectPopupWindow.showAsDropDown(select_parent, 0, -3);
    }

    private void initPopuWindow() {
        initDatas();

        View loginwindow = (View) getActivity().getLayoutInflater().inflate(R.layout.select_options,
                null);
        select_listView = (ListView) loginwindow.findViewById(R.id.list);

        //设置自定义Adapter
        optionsAdapter = new OptionsAdapter(getActivity(), select_handler, Select_datas);
        select_listView.setAdapter(optionsAdapter);

        selectPopupWindow = new PopupWindow(loginwindow, pwidth, LinearLayout.LayoutParams
                .WRAP_CONTENT, true);

        selectPopupWindow.setOutsideTouchable(true);

        //这一句是为了实现弹出PopupWindow后,当点击屏幕其他部分及Back键时PopupWindow会消失,
        //没有这一句则效果不能出来,但并不会影响背景
        //本人能力极其有限,不明白其原因,还望高手、知情者指点一下
        selectPopupWindow.setBackgroundDrawable(new BitmapDrawable());
    }

    private void bindViews() {
        img_1 = (ImageView) view.findViewById(R.id.img_1);
        et_1 = (EditText) view.findViewById(R.id.et_1);
    }

    @Override
    public boolean handleMessage(Message msg) {
        Bundle data = msg.getData();
        switch (msg.what) {
            case 3:
                //选中下拉项,下拉框消失
                int selIndex = data.getInt("selIndex");
                et_1.setText(Select_datas.get(selIndex));
                dismiss();
                break;
            case 4:
                //移除下拉项数据
                int delIndex = data.getInt("delIndex");
                Select_datas.remove(delIndex);
                //刷新下拉列表
                optionsAdapter.notifyDataSetChanged();
                break;
        }
        return false;
    }

    /**
     * PopupWindow消失
     */
    public void dismiss() {
        selectPopupWindow.dismiss();
    }
}

 

Git地址:【https://github.com/qq576777915/PopupWindowTest/】

 

参考资料:

https://blog.csdn.net/jdsjlzx/article/details/41789779

https://stackoverflow.com/questions/30129984/how-to-get-the-onwindowfocuschanged-on-fragment

One Reply to “Android实现基于Fragment的多账号下拉列表实现Demo”

  1. Hello, let’s be friends
    ??Latest USA news. We n we publish all of them hot and advanced facts Russia, estimates experts. All negative in the world is created with the quiet tacit consent of the indifferent. No one provides us with incentives. We are Enthusiasts. We are building a civil society. The people are the bearer of sovereignty and the only source of power. No one can usurp power. Useful topics – Technologies and Science Motel News

    Florida Business

    TWITTER
    FACEBOOK
    GOOGLE+
    riverside

发表评论

电子邮件地址不会被公开。 必填项已用*标注