效果
PopWinLayout
package com. coral3. common_module. components ; import android. content. Context ;
import android. os. Handler ;
import android. os. Message ;
import android. util. AttributeSet ;
import android. view. Gravity ;
import android. view. LayoutInflater ;
import android. view. View ;
import android. view. ViewGroup ;
import android. widget. AdapterView ;
import android. widget. ImageView ;
import android. widget. LinearLayout ;
import android. widget. ListView ;
import android. widget. PopupWindow ;
import androidx. annotation. Nullable ;
import com. coral3. common_module. R ;
import com. coral3. common_module. adapter. PopWindowAdapter ;
import com. coral3. common_module. model. PopModel ;
import java. util. ArrayList ;
import java. util. List ; public class PopWinLayout extends LinearLayout { private Context mContext; private ListView lv; private ImageView asDropDownView; private PopupWindow window; private List data = new ArrayList < > ( ) ; private View view; private PopWindowAdapter adapter; private int windowWidth = 363 ; private Boolean popWinIsShow = false ; private ICallback mICallback; private Handler handler = new Handler ( new Handler. Callback ( ) { @Override public boolean handleMessage ( Message message) { if ( message. what == 0x00 ) popWinIsShow = false ; return false ; } } ) ; public PopWinLayout ( Context context, @Nullable AttributeSet attrs) { super ( context, attrs) ; mContext = context; initView ( ) ; initLocalData ( ) ; initPop ( ) ; initLisener ( ) ; } private void initView ( ) { view = LayoutInflater . from ( mContext) . inflate ( R . layout. layout_pop_window, this ) ; } private void initLisener ( ) { window. setOnDismissListener ( new PopupWindow. OnDismissListener ( ) { @Override public void onDismiss ( ) { handler. sendEmptyMessageDelayed ( 0x00 , 100 ) ; } } ) ; lv. setOnItemClickListener ( new AdapterView. OnItemClickListener ( ) { @Override public void onItemClick ( AdapterView < ? > adapterView, View view, int i, long l) { mICallback. onItemClick ( i, ( ( PopModel ) data. get ( i) ) . getText ( ) ) ; hidePopView ( ) ; } } ) ; } private void initLocalData ( ) { data. add ( new PopModel ( R . mipmap. msg, "发起群聊" ) ) ; data. add ( new PopModel ( R . mipmap. msg, "添加好友" ) ) ; data. add ( new PopModel ( R . mipmap. msg, "扫一扫" ) ) ; data. add ( new PopModel ( R . mipmap. msg, "收付款" ) ) ; data. add ( new PopModel ( R . mipmap. msg, "帮助与反馈" ) ) ; } private void initPop ( ) { lv = view. findViewById ( R . id. lv_pop_list) ; adapter = new PopWindowAdapter ( mContext, R . layout. custom_spinner_dropdown_item, data) ; lv. setAdapter ( adapter) ; window = new PopupWindow ( this ) ; window. setContentView ( view) ; window. setHeight ( ViewGroup. LayoutParams . WRAP_CONTENT ) ; window. setWidth ( windowWidth) ; window. setOutsideTouchable ( true ) ; } public void setDropDownBtn ( ImageView v) { asDropDownView = v; } public void showPopView ( ) { if ( null != asDropDownView) { window. showAsDropDown ( asDropDownView, 0 , 33 , Gravity . RIGHT ) ; popWinIsShow = true ; } } public void hidePopView ( ) { if ( null != asDropDownView) { window. dismiss ( ) ; popWinIsShow = false ; } } public void setData ( List data) { this . data = data; adapter. notifyDataSetChanged ( ) ; } public Boolean getPopWinStatus ( ) { return popWinIsShow; } public void setPopWinStatus ( Boolean status) { popWinIsShow = status; } public void setICallback ( ICallback iCallback) { mICallback = iCallback; } public interface ICallback { void onItemClick ( int pos, String name) ; }
}
## PopModel
package com. coral3. common_module. model ; public class PopModel { private int imageId; private String text; public int getImageId ( ) { return imageId; } public void setImageId ( int imageId) { this . imageId = imageId; } public String getText ( ) { return text; } public void setText ( String text) { this . text = text; } public PopModel ( int imageId, String text) { this . imageId = imageId; this . text = text; } public PopModel ( ) { }
}
TitleLayout
package com. coral3. common_module. components ; import android. content. Context ;
import android. util. AttributeSet ;
import android. view. LayoutInflater ;
import android. view. MotionEvent ;
import android. view. View ;
import android. widget. ImageView ;
import android. widget. LinearLayout ;
import android. widget. TextView ;
import androidx. annotation. Nullable ;
import com. coral3. common_module. R ; public class TitleLayout extends LinearLayout { private TextView title; private Context mContext; private View view; private TextView back; private ImageView btnRight; private PopWinLayout popLayout; public TitleLayout ( Context context, @Nullable AttributeSet attrs) { super ( context, attrs) ; mContext = context; initView ( ) ; initListener ( ) ; } private void initView ( ) { view = LayoutInflater . from ( mContext) . inflate ( R . layout. layout_title, this ) ; back = view. findViewById ( R . id. btn_back) ; btnRight = view. findViewById ( R . id. btn_right) ; title = view. findViewById ( R . id. tv_title) ; title. setText ( "标题" ) ; popLayout = new PopWinLayout ( mContext, null ) ; popLayout. setDropDownBtn ( btnRight) ; } private void initListener ( ) { back. setOnClickListener ( new OnClickListener ( ) { @Override public void onClick ( View view) { } } ) ; btnRight. setOnClickListener ( new OnClickListener ( ) { @Override public void onClick ( View view) { if ( popLayout. getPopWinStatus ( ) ) { popLayout. hidePopView ( ) ; } else { popLayout. showPopView ( ) ; } } } ) ; } @Override public boolean onTouchEvent ( MotionEvent arg0) { getParent ( ) . requestDisallowInterceptTouchEvent ( true ) ; return true ; } public void showRightView ( ) { btnRight. setVisibility ( View . VISIBLE ) ; } public void setTitle ( String v) { title. setText ( v) ; } public void setRightItemCallback ( PopWinLayout. ICallback iCallback) { if ( null != popLayout) popLayout. setICallback ( iCallback) ; }
}
Triangle
package com. coral3. common_module. components ; import android. content. Context ;
import android. graphics. Canvas ;
import android. graphics. Color ;
import android. graphics. Paint ;
import android. graphics. Path ;
import android. util. AttributeSet ;
import android. view. View ;
import androidx. annotation. Nullable ;
import com. coral3. common_module. utils. DensityUtils ; public class Triangle extends View { private int mWidth = 0 ; private int mHeight = 0 ; private Context mContext; public Triangle ( Context context, @Nullable AttributeSet attrs) { super ( context, attrs) ; this . mContext = context; initView ( ) ; } public Triangle ( Context context) { super ( context) ; } private void initView ( ) { mWidth = DensityUtils . dp2px ( 10 ) ; mHeight = DensityUtils . dp2px ( 6 ) ; } @Override protected void onMeasure ( int widthMeasureSpec, int heightMeasureSpec) { super . onMeasure ( widthMeasureSpec, heightMeasureSpec) ; setMeasuredDimension ( mWidth, mHeight) ; } @Override protected void onDraw ( Canvas canvas) { super . onDraw ( canvas) ; Paint paint = new Paint ( ) ; paint. setColor ( Color . parseColor ( "#434343" ) ) ; paint. setAntiAlias ( true ) ; paint. setStyle ( Paint. Style . FILL ) ; Path path = new Path ( ) ; path. moveTo ( 0 , mHeight) ; path. lineTo ( mWidth, mHeight) ; path. lineTo ( mWidth/ 2 , 0 ) ; path. close ( ) ; canvas. drawPath ( path, paint) ; }
}
PopWindowAdapter
package com. coral3. common_module. adapter ; import android. content. Context ;
import android. view. LayoutInflater ;
import android. view. View ;
import android. view. ViewGroup ;
import android. widget. ArrayAdapter ;
import android. widget. ImageView ;
import android. widget. TextView ;
import androidx. annotation. NonNull ;
import androidx. annotation. Nullable ;
import com. coral3. common_module. R ;
import com. coral3. common_module. model. PopModel ;
import java. util. List ; public class PopWindowAdapter extends ArrayAdapter < PopModel > { private int resource; private Context context; public PopWindowAdapter ( @NonNull Context context, int resource, @NonNull List < PopModel > objects) { super ( context, resource, objects) ; this . resource = resource; this . context = context; } @NonNull @Override public View getView ( int position, @Nullable View convertView, @NonNull ViewGroup parent) { PopModel popModel = getItem ( position) ; MyHolder myHolder = new MyHolder ( ) ; if ( null == convertView) { convertView = LayoutInflater . from ( context) . inflate ( resource, parent, false ) ; myHolder. ivFruit = convertView. findViewById ( R . id. iv_fruit) ; myHolder. tvFruit = convertView. findViewById ( R . id. tv_fruit) ; convertView. setTag ( myHolder) ; } else { myHolder = ( MyHolder ) convertView. getTag ( ) ; } myHolder. ivFruit. setImageResource ( popModel. getImageId ( ) ) ; myHolder. tvFruit. setText ( popModel. getText ( ) ) ; return convertView; } class MyHolder { ImageView ivFruit; TextView tvFruit; }
}
DensityUtils
package com. coral3. common_module. utils ; import android. util. TypedValue ;
public class DensityUtils { private DensityUtils ( ) { throw new UnsupportedOperationException ( "cannot be instantiated" ) ; } public static int dp2px ( float dpVal) { return ( int ) TypedValue . applyDimension ( TypedValue . COMPLEX_UNIT_DIP , dpVal, InitUtil . getContext ( ) . getResources ( ) . getDisplayMetrics ( ) ) ; } public static int sp2px ( float spVal) { return ( int ) TypedValue . applyDimension ( TypedValue . COMPLEX_UNIT_SP , spVal, InitUtil . getContext ( ) . getResources ( ) . getDisplayMetrics ( ) ) ; } public static float px2dp ( float pxVal) { final float scale = InitUtil . getContext ( ) . getResources ( ) . getDisplayMetrics ( ) . density; return ( pxVal / scale) ; } public static float px2sp ( float pxVal) { return ( pxVal / InitUtil . getContext ( ) . getResources ( ) . getDisplayMetrics ( ) . scaledDensity) ; }
}
ToastUtil
package com. coral3. common_module. utils ; import android. content. Context ;
import android. view. Gravity ;
import android. widget. Toast ; public class ToastUtil { public static Toast toast; public static void showMsg ( Context context, String msg) { if ( toast != null ) toast. cancel ( ) ; toast = Toast . makeText ( context, msg, Toast . LENGTH_SHORT ) ; toast. setGravity ( Gravity . CENTER , 0 , 0 ) ; toast. show ( ) ; }
}
DetailActivity
package com. coral3. ah. ui ; import androidx. appcompat. app. AppCompatActivity ;
import android. os. Bundle ;
import com. coral3. ah. R ;
import com. coral3. common_module. components. PopWinLayout ;
import com. coral3. common_module. components. TitleLayout ;
import com. coral3. common_module. utils. ToastUtil ; public class DetailActivity extends AppCompatActivity implements PopWinLayout. ICallback { private TitleLayout titleLayout; @Override protected void onCreate ( Bundle savedInstanceState) { super . onCreate ( savedInstanceState) ; setContentView ( R . layout. activity_detail) ; initView ( ) ; initListener ( ) ; } private void initView ( ) { titleLayout = findViewById ( R . id. tl_title) ; titleLayout. showRightView ( ) ; titleLayout. setTitle ( "详情" ) ; } private void initListener ( ) { titleLayout. setRightItemCallback ( this ) ; } @Override public void onItemClick ( int pos, String name) { ToastUtil . showMsg ( DetailActivity . this , name) ; }
}
layout_pop_window.xml
<?xml version="1.0" encoding="utf-8"?>
< LinearLayout xmlns: android= " http://schemas.android.com/apk/res/android" android: layout_width= " wrap_content" android: orientation= " vertical" android: layout_height= " wrap_content" > < com.coral3.common_module.components.Triangleandroid: layout_width= " wrap_content" android: layout_height= " wrap_content" android: layout_marginLeft= " 33dp" android: layout_gravity= " center_horizontal" /> < LinearLayoutandroid: background= " @drawable/bg_radius" android: layout_width= " wrap_content" android: layout_height= " wrap_content" > < ListViewandroid: id= " @+id/lv_pop_list" android: divider= " #434343" android: dividerHeight= " 0.1dp" android: layout_width= " wrap_content" android: layout_height= " wrap_content" /> </ LinearLayout>
</ LinearLayout>
bg_radius
<?xml version="1.0" encoding="utf-8"?>
< LinearLayout xmlns: android= " http://schemas.android.com/apk/res/android" android: layout_width= " wrap_content" android: orientation= " vertical" android: layout_height= " wrap_content" > < com.coral3.common_module.components.Triangleandroid: layout_width= " wrap_content" android: layout_height= " wrap_content" android: layout_marginLeft= " 33dp" android: layout_gravity= " center_horizontal" /> < LinearLayoutandroid: background= " @drawable/bg_radius" android: layout_width= " wrap_content" android: layout_height= " wrap_content" > < ListViewandroid: id= " @+id/lv_pop_list" android: divider= " #434343" android: dividerHeight= " 0.1dp" android: layout_width= " wrap_content" android: layout_height= " wrap_content" /> </ LinearLayout>
</ LinearLayout>