データベースから選択した単語のリストを表示するカスタムListViewがあります。このリストビューアイテムをスワイプすると、下の画像のような[削除]ボタンが表示されます。そして、そのボタンを押すと、データベースから削除され、リストビューが更新されます。 m
私はすでにこのサンプルコードを調べています here 。しかし、まだ機能しません。
編集:他のオプションの間に、あなたの問題を解決できる素敵なライブラリがあります: https://github.com/daimajia/AndroidSwipeLayout
私はグーグルを何度も検索して、最適なプロジェクトがswipmenulistview https://github.com/baoyongzhang/SwipeMenuListView githubであると見つけました。
私はそれを行うのに良いライブラリを見つけるのと同じ問題を抱えていました。最終的に、私はそれを行うことができるライブラリを作成しました: SwipeRevealLayout
Gradleファイル:
dependencies {
compile 'com.chauthai.swipereveallayout:swipe-reveal-layout:1.4.0'
}
Xmlファイルで:
<com.chauthai.swipereveallayout.SwipeRevealLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:mode="same_level"
app:dragEdge="left">
<!-- Your secondary layout here -->
<FrameLayout
Android:layout_width="wrap_content"
Android:layout_height="match_parent" />
<!-- Your main layout here -->
<FrameLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
</com.chauthai.swipereveallayout.SwipeRevealLayout>
次に、アダプターファイルで:
public class Adapter extends RecyclerView.Adapter {
// This object helps you save/restore the open/close state of each view
private final ViewBinderHelper viewBinderHelper = new ViewBinderHelper();
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// get your data object first.
YourDataObject dataObject = mDataSet.get(position);
// Save/restore the open/close state.
// You need to provide a String id which uniquely defines the data object.
viewBinderHelper.bind(holder.swipeRevealLayout, dataObject.getId());
// do your regular binding stuff here
}
}
githubのデモ を作成しました。右から左にスワイプすると削除ボタンが表示され、ListViewからアイテムを削除してListViewを更新できます。
ListItemでViewSwitcherを使用して彼の仕事を手に入れました。
list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="horizontal" >
<ViewSwitcher
Android:id="@+id/list_switcher"
Android:layout_width="match_parent"
Android:layout_height="fill_parent"
Android:inAnimation="@Android:anim/slide_in_left"
Android:outAnimation="@Android:anim/slide_out_right"
Android:measureAllChildren="false" >
<TextView
Android:id="@+id/tv_item_name"
Android:layout_width="match_parent"
Android:layout_height="50dp"
Android:layout_gravity="center_vertical"
Android:maxHeight="50dp"
Android:paddingLeft="10dp" />
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="horizontal"
Android:clickable="false"
Android:gravity="center"
>
<Button
Android:id="@+id/b_edit_in_list"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="Edit"
Android:paddingLeft="20dp"
Android:paddingRight="20dp"
/>
<Button
Android:id="@+id/b_delete_in_list"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="Delete"
Android:paddingLeft="20dp"
Android:paddingRight="20dp"
Android:background="@Android:color/holo_red_dark"
/>
</LinearLayout>
</ViewSwitcher>
ListAdapter:getView()メソッドの[編集]ボタンと[削除]ボタンにOnclickListenersを実装します。ここでのキャッチは、onClickメソッド内でクリックされたListItemの位置を取得することです。これにはsetTag()およびgetTag()メソッドが使用されます。
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
final ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_item, null);
viewHolder.viewSwitcher=(ViewSwitcher)convertView.findViewById(R.id.list_switcher);
viewHolder.itemName = (TextView) convertView
.findViewById(R.id.tv_item_name);
viewHolder.deleteitem=(Button)convertView.findViewById(R.id.b_delete_in_list);
viewHolder.deleteItem.setTag(position);
viewHolder.editItem=(Button)convertView.findViewById(R.id.b_edit_in_list);
viewHolder.editItem.setTag(position);
viewHolder.deleteItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
fragment.deleteItemList((Integer)v.getTag());
}
});
viewHolder.editItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
fragment.editItemList(position);
}
});
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.itemName.setText(itemlist[position]);
return convertView;
}
フラグメントに、ジェスチャーリスナーを追加して、フリングジェスチャーを検出します。
public class MyGestureListener extends SimpleOnGestureListener {
private ListView list;
public MyGestureListener(ListView list) {
this.list = list;
}
// CONDITIONS ARE TYPICALLY VELOCITY OR DISTANCE
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// if (INSERT_CONDITIONS_HERE)
ltor=(e2.getX()-e1.getX()>DELTA_X);
if (showDeleteButton(e1))
{
return true;
}
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// TODO Auto-generated method stub
return super.onScroll(e1, e2, distanceX, distanceY);
}
private boolean showDeleteButton(MotionEvent e1) {
int pos = list.pointToPosition((int) e1.getX(), (int) e1.getY());
return showDeleteButton(pos);
}
private boolean showDeleteButton(int pos) {
View child = list.getChildAt(pos);
if (child != null) {
Button delete = (Button) child
.findViewById(R.id.b_edit_in_list);
ViewSwitcher viewSwitcher = (ViewSwitcher) child
.findViewById(R.id.Host_list_switcher);
TextView hostName = (TextView) child
.findViewById(R.id.tv_Host_name);
if (delete != null) {
viewSwitcher.setInAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.slide_in_left));
viewSwitcher.setOutAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.slide_out_right));
}
viewSwitcher.showNext();
// frameLayout.setVisibility(View.VISIBLE);
}
return true;
}
return false;
}
}
FragmentのonCreateViewメソッドで、
GestureDetector gestureDetector = new GestureDetector(getActivity(),
new MyGestureListener(hostList));
hostList.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if (gestureDetector.onTouchEvent(event)) {
return true;
} else {
return false;
}
}
});
これは私のために働いた。もっと洗練すべきです。
そこにリンクが非常に素晴らしく、簡単だった参照してください。正常に動作しています...正常に動作するライブラリは必要ありません。 こちら をクリックします
OnTouchListener gestureListener = new View.OnTouchListener() {
private int padding = 0;
private int initialx = 0;
private int currentx = 0;
private ViewHolder viewHolder;
public boolean onTouch(View v, MotionEvent event) {
if ( event.getAction() == MotionEvent.ACTION_DOWN) {
padding = 0;
initialx = (int) event.getX();
currentx = (int) event.getX();
viewHolder = ((ViewHolder) v.getTag());
}
if ( event.getAction() == MotionEvent.ACTION_MOVE) {
currentx = (int) event.getX();
padding = currentx - initialx;
}
if ( event.getAction() == MotionEvent.ACTION_UP ||
event.getAction() == MotionEvent.ACTION_CANCEL) {
padding = 0;
initialx = 0;
currentx = 0;
}
if(viewHolder != null) {
if(padding == 0) {
v.setBackgroundColor(0xFF000000 );
if(viewHolder.running)
v.setBackgroundColor(0xFF058805);
}
if(padding > 75) {
viewHolder.running = true;
v.setBackgroundColor(0xFF00FF00 );
viewHolder.icon.setImageResource(R.drawable.clock_running);
}
if(padding < -75) {
viewHolder.running = false;
v.setBackgroundColor(0xFFFF0000 );
}
v.setPadding(padding, 0,0, 0);
}
return true;
}
};
削除するスワイプとドラッグによるアイテムの並べ替えの両方を組み合わせたリストビューを示すアプリを利用できます。コードは、削除するためにスワイプするためのChet Haaseのコードと、並べ替えるためにドラッグするためのDaniel Olshanskyのコードに基づいています。
Chetのコードはアイテムをすぐに削除します。スワイプするとアイテムが削除されたことを示す下部ビューが表示され、ユーザーが削除を取り消すことができる[元に戻す]ボタンが表示されるGmailのように機能するように改善しました。 Chetのコードにもバグがあります。リストビューのアイテムの高さがリストビューの高さよりも少ない場合、最後のアイテムを削除すると、最後のアイテムは削除されないように見えます。これは私のコードで修正されました。
ダニエルのコードでは、アイテムを長押しする必要があります。多くのユーザーは、これが隠された機能になる傾向があるため、直感的ではないと感じています。代わりに、「移動」ボタンを許可するようにコードを変更しました。ボタンを押してアイテムをドラッグするだけです。これは、ニューストピックを並べ替えるときのGoogleニュースアプリの動作とほぼ一致しています。
ソースコードとデモアプリは次の場所で入手できます。 https://github.com/JohannBlake/ListViewOrderAndSwipe
チェットとダニエルは両方ともGoogleの出身です。
アイテムの削除に関するChetのビデオは、次の場所で見ることができます。 https://www.youtube.com/watch?v=YCHNAi9kJI4
アイテムの並べ替えに関するダニエルのビデオは、次の場所で見ることができます。 https://www.youtube.com/watch?v=_BZIvjMgH-Q
かなりの量の作業が、これらすべてを接着して、見かけのないUIエクスペリエンスを提供するために行われました。 Githubでプロジェクトにスターを付けてください。
この機能をゼロから実装するのは時間の無駄です。 SalutonMondoが推奨するライブラリを実装し、非常に満足しています。使い方は非常に簡単で、非常に迅速です。元のライブラリを改善し、アイテムクリック用の新しいクリックリスナーを追加しました。また、フォントの素晴らしいライブラリ( http://fortawesome.github.io/Font-Awesome/ )を追加し、新しいアイテムタイトルを追加して、フォントawesomeからアイコン名を指定できるようになりました。
ここ はgithubリンクです
これを達成するために、私はたくさんのサードパーティのライブラリを試しました。しかし、それらのどれも私が欲しかった滑らかさと使いやすさの経験を示していません。それから私は自分でそれを書くことにしました。そして結果は、まあ、私はそれが大好きだった。ここでコードを共有します。たぶん、私はそれを将来どのリサイクラービューにも埋め込むことができるライブラリとして書くでしょう。しかし、今のところはコードです。
注:私はリサイクラービューとViewHolderを使用しています。一部の値はハードコーディングされているため、要件に応じて変更してください。
row_layout.xml
<LinearLayout
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentRight="true"
Android:orientation="horizontal">
<Button
Android:id="@+id/slide_button_2"
Android:text="Button2"
Android:layout_width="80dp"
Android:layout_height="80dp" />
<Button
Android:id="@+id/slide_button_1"
Android:text="Button1"
Android:layout_width="80dp"
Android:layout_height="80dp" />
</LinearLayout>
<LinearLayout
Android:id="@+id/chat_row_cell"
Android:layout_width="match_parent"
Android:layout_height="80dp"
Android:orientation="horizontal"
Android:background="@color/white">
<ImageView
Android:id="@+id/chat_image"
Android:layout_width="60dp"
Android:layout_height="60dp"
Android:layout_marginLeft="10dp"
Android:layout_marginTop="10dp"
Android:layout_marginBottom="10dp"
Android:layout_marginRight="10dp"
Android:layout_gravity="center"/>
<LinearLayout
Android:layout_width="0dp"
Android:layout_height="match_parent"
Android:layout_weight="1"
Android:gravity="center">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical">
<TextView
Android:id="@+id/chat_title"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:textColor="@color/md_grey_800"
Android:textSize="18sp"/>
<TextView
Android:id="@+id/chat_subtitle"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:textColor="@color/md_grey_600"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
ChatAdaptor.Java
パブリッククラスChatAdaptorはRecyclerView.Adapterを拡張します{
List<MXGroupChatSession> sessions;
Context context;
ChatAdaptorInterface listener;
public interface ChatAdaptorInterface{
void cellClicked(MXGroupChatSession session);
void utilityButton1Clicked(MXGroupChatSession session);
void utilityButton2Clicked(MXGroupChatSession session);
}
public ChatAdaptor(List<MXGroupChatSession> sessions, ChatAdaptorInterface listener, Context context){
this.sessions=sessions;
this.context=context;
this.listener=listener;
}
@Override
public ChatViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=(View)LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_row,null);
ChatViewHolder chatViewHolder=new ChatViewHolder(view);
return chatViewHolder;
}
@Override
public void onBindViewHolder(ChatViewHolder holder, final int position) {
MXGroupChatSession session=this.sessions.get(position);
holder.selectedSession=session;
holder.titleView.setText(session.getTopic());
holder.subtitleView.setText(session.getLastFeedContent());
Picasso.with(context).load(new File(session.getCoverImagePath())).transform(new CircleTransformPicasso()).into(holder.imageView);
}
@Override
public int getItemCount() {
return sessions.size();
}
public class ChatViewHolder extends RecyclerView.ViewHolder{
ImageView imageView;
TextView titleView;
TextView subtitleView;
ViewGroup cell;
ViewGroup cellContainer;
Button button1;
Button button2;
MXGroupChatSession selectedSession;
private GestureDetectorCompat gestureDetector;
float totalx;
float buttonTotalWidth;
Boolean open=false;
Boolean isScrolling=false;
public ChatViewHolder(View itemView) {
super(itemView);
cell=(ViewGroup) itemView.findViewById(R.id.chat_row_cell);
cellContainer=(ViewGroup) itemView.findViewById(R.id.chat_row_container);
button1=(Button) itemView.findViewById(R.id.slide_button_1);
button2=(Button) itemView.findViewById(R.id.slide_button_2);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.utilityButton1Clicked(selectedSession);
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.utilityButton2Clicked(selectedSession);
}
});
ViewTreeObserver vto = cellContainer.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
buttonTotalWidth = button1.getWidth()+button2.getWidth();
}
});
this.titleView=(TextView)itemView.findViewById(R.id.chat_title);
subtitleView=(TextView)itemView.findViewById(R.id.chat_subtitle);
imageView=(ImageView)itemView.findViewById(R.id.chat_image);
gestureDetector=new GestureDetectorCompat(context,new ChatRowGesture());
cell.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(gestureDetector.onTouchEvent(event)){
return true;
}
if(event.getAction() == MotionEvent.ACTION_UP) {
if(isScrolling ) {
isScrolling = false;
handleScrollFinished();
};
}
else if(event.getAction() == MotionEvent.ACTION_CANCEL){
if(isScrolling ) {
isScrolling = false;
handleScrollFinished();
};
}
return false;
}
});
}
public class ChatRowGesture extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (!open){
listener.cellClicked(selectedSession);
}
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
isScrolling=true;
totalx=totalx+distanceX;
freescroll(totalx);
return true;
}
}
void handleScrollFinished(){
if (open){
if (totalx>2*buttonTotalWidth/3){
slideLeft();
totalx=buttonTotalWidth;
}else{
slideRight();
totalx=0;
}
}else{
if (totalx>buttonTotalWidth/3){
slideLeft();
totalx=buttonTotalWidth;
}else{
slideRight();
totalx=0;
}
}
}
void slideRight(){
TransitionManager.beginDelayedTransition(cellContainer);
ViewGroup.MarginLayoutParams params;
params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams();
params.setMargins(0,0,0,0);
cell.setLayoutParams(params);
open=false;
}
void slideLeft(){
TransitionManager.beginDelayedTransition(cellContainer);
ViewGroup.MarginLayoutParams params;
params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams();
params.setMargins(((int)buttonTotalWidth*-1),0,(int)buttonTotalWidth,0);
cell.setLayoutParams(params);
open=true;
}
void freescroll(float x){
if (x<buttonTotalWidth && x>0){
int xint=(int)x;
ViewGroup.MarginLayoutParams params;
params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams();
params.setMargins(params.leftMargin,0,xint,0);
cell.setLayoutParams(params);
}
}
}
これが誰かを助けることを願っています!!
レイアウト.xmlでViewPagerを定義します。
<Android.support.v4.view.ViewPager
Android:id="@+id/example_pager"
Android:layout_width="fill_parent"
Android:layout_height="@dimen/abc_action_bar_default_height" />
次に、アクティビティ/フラグメントで、カスタムページャーアダプターを設定します。
アクティビティ内:
protected void onCreate(Bundle savedInstanceState) {
PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager());
ViewPager pager = (ViewPager) findViewById(R.id.example_pager);
pager.setAdapter(adapter);
// pager.setOnPageChangeListener(this); // You can set a page listener here
pager.setCurrentItem(0);
}
フラグメント内:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout, container, false);
if (view != null) {
PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager());
ViewPager pager = (ViewPager) view.findViewById(R.id.example_pager);
pager.setAdapter(adapter);
// pager.setOnPageChangeListener(this); // You can set a page listener here
pager.setCurrentItem(0);
}
return view;
}
カスタムページャークラスを作成します。
// setup your PagerAdapter which extends FragmentPagerAdapter
class PagerAdapter extends FragmentPagerAdapter {
public static final int NUM_PAGES = 2;
private CustomFragment[] mFragments = new CustomFragment[NUM_PAGES];
public PagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@ Override
public int getCount() {
return NUM_PAGES;
}
@ Override
public Fragment getItem(int position) {
if (mFragments[position] == null) {
// this calls the newInstance from when you setup the ListFragment
mFragments[position] = new CustomFragment();
}
return mFragments[position];
}
}