parent
87070d52ca
commit
d230c1029d
Binary file not shown.
@ -0,0 +1,265 @@ |
|||||||
|
package xyz.fycz.myreader.ui.activity; |
||||||
|
|
||||||
|
import android.annotation.SuppressLint; |
||||||
|
import android.content.DialogInterface; |
||||||
|
import android.content.Intent; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.os.Handler; |
||||||
|
import android.view.Menu; |
||||||
|
import android.view.MenuItem; |
||||||
|
import android.view.MotionEvent; |
||||||
|
import android.widget.LinearLayout; |
||||||
|
|
||||||
|
import androidx.annotation.Nullable; |
||||||
|
import androidx.appcompat.app.AppCompatActivity; |
||||||
|
import androidx.appcompat.widget.Toolbar; |
||||||
|
import androidx.documentfile.provider.DocumentFile; |
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager; |
||||||
|
import androidx.recyclerview.widget.RecyclerView; |
||||||
|
|
||||||
|
import com.mcxtzhang.swipemenulib.SwipeMenuLayout; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import butterknife.BindView; |
||||||
|
import io.reactivex.Observable; |
||||||
|
import io.reactivex.ObservableOnSubscribe; |
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers; |
||||||
|
import io.reactivex.annotations.NonNull; |
||||||
|
import io.reactivex.schedulers.Schedulers; |
||||||
|
import xyz.fycz.myreader.R; |
||||||
|
import xyz.fycz.myreader.base.BaseActivity; |
||||||
|
import xyz.fycz.myreader.base.observer.MyObserver; |
||||||
|
import xyz.fycz.myreader.base.observer.MySingleObserver; |
||||||
|
import xyz.fycz.myreader.common.APPCONST; |
||||||
|
import xyz.fycz.myreader.greendao.entity.ReplaceRuleBean; |
||||||
|
import xyz.fycz.myreader.model.ReplaceRuleManager; |
||||||
|
import xyz.fycz.myreader.ui.adapter.ReplaceRuleAdapter; |
||||||
|
import xyz.fycz.myreader.ui.dialog.DialogCreator; |
||||||
|
import xyz.fycz.myreader.ui.dialog.MyAlertDialog; |
||||||
|
import xyz.fycz.myreader.ui.dialog.ReplaceDialog; |
||||||
|
import xyz.fycz.myreader.util.ToastUtils; |
||||||
|
import xyz.fycz.myreader.util.utils.ClipBoardUtil; |
||||||
|
import xyz.fycz.myreader.util.utils.FileUtils; |
||||||
|
import xyz.fycz.myreader.util.utils.GsonExtensionsKt; |
||||||
|
import xyz.fycz.myreader.widget.DividerItemDecoration; |
||||||
|
|
||||||
|
import static android.text.TextUtils.isEmpty; |
||||||
|
import static xyz.fycz.myreader.util.UriFileUtil.getPath; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2021/1/19 10:02 |
||||||
|
*/ |
||||||
|
public class RuleActivity extends BaseActivity { |
||||||
|
@BindView(R.id.rv_rule_list) |
||||||
|
RecyclerView rvRuleList; |
||||||
|
|
||||||
|
private List<ReplaceRuleBean> mReplaceRules; |
||||||
|
private ReplaceRuleAdapter mAdapter; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected int getContentId() { |
||||||
|
return R.layout.activity_rule; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initData(Bundle savedInstanceState) { |
||||||
|
super.initData(savedInstanceState); |
||||||
|
ReplaceRuleManager.getAll().subscribe(new MySingleObserver<List<ReplaceRuleBean>>() { |
||||||
|
@Override |
||||||
|
public void onSuccess(@NonNull List<ReplaceRuleBean> replaceRuleBeans) { |
||||||
|
mReplaceRules = replaceRuleBeans; |
||||||
|
initRuleList(); |
||||||
|
setUpBarTitle(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onError(Throwable e) { |
||||||
|
ToastUtils.showError("数据加载失败\n" + e.getLocalizedMessage()); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void setUpToolbar(Toolbar toolbar) { |
||||||
|
super.setUpToolbar(toolbar); |
||||||
|
setUpBarTitle(); |
||||||
|
setStatusBarColor(R.color.colorPrimary, true); |
||||||
|
} |
||||||
|
|
||||||
|
private void setUpBarTitle() { |
||||||
|
getSupportActionBar().setTitle(String.format("%s(共%s个)", |
||||||
|
getString(R.string.replace_rule), mReplaceRules == null ? 0 : mReplaceRules.size())); |
||||||
|
} |
||||||
|
|
||||||
|
protected void initRuleList() { |
||||||
|
mAdapter = new ReplaceRuleAdapter(this, (which, data) -> { |
||||||
|
mReplaceRules.remove(data); |
||||||
|
mAdapter.notifyItemRemoved(which); |
||||||
|
mAdapter.removeItem2(data); |
||||||
|
setUpBarTitle(); |
||||||
|
}); |
||||||
|
rvRuleList.setLayoutManager(new LinearLayoutManager(this)); |
||||||
|
rvRuleList.setAdapter(mAdapter); |
||||||
|
//设置分割线
|
||||||
|
rvRuleList.addItemDecoration(new DividerItemDecoration(this)); |
||||||
|
mAdapter.refreshItems(mReplaceRules); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility") |
||||||
|
@Override |
||||||
|
protected void initClick() { |
||||||
|
super.initClick(); |
||||||
|
rvRuleList.setOnTouchListener((v, event) -> { |
||||||
|
if (event.getAction() == MotionEvent.ACTION_UP) { |
||||||
|
SwipeMenuLayout viewCache = SwipeMenuLayout.getViewCache(); |
||||||
|
if (null != viewCache) { |
||||||
|
viewCache.smoothClose(); |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onCreateOptionsMenu(Menu menu) { |
||||||
|
getMenuInflater().inflate(R.menu.menu_rule, menu); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onOptionsItemSelected(MenuItem item) { |
||||||
|
switch (item.getItemId()) { |
||||||
|
case R.id.action_add_rule: |
||||||
|
ReplaceRuleBean newRuleBean = new ReplaceRuleBean(); |
||||||
|
newRuleBean.setReplaceSummary(""); |
||||||
|
newRuleBean.setEnable(true); |
||||||
|
newRuleBean.setRegex(""); |
||||||
|
newRuleBean.setIsRegex(false); |
||||||
|
newRuleBean.setReplacement(""); |
||||||
|
newRuleBean.setSerialNumber(0); |
||||||
|
newRuleBean.setUseTo(""); |
||||||
|
ReplaceDialog replaceDialog = new ReplaceDialog(this, newRuleBean |
||||||
|
, () -> { |
||||||
|
ToastUtils.showSuccess("内容替换规则添加成功!"); |
||||||
|
mReplaceRules.add(newRuleBean); |
||||||
|
mAdapter.addItem(newRuleBean); |
||||||
|
setUpBarTitle(); |
||||||
|
refreshUI(); |
||||||
|
}); |
||||||
|
replaceDialog.show(getSupportFragmentManager(), "replaceRule"); |
||||||
|
break; |
||||||
|
case R.id.action_import: |
||||||
|
MyAlertDialog.build(this) |
||||||
|
.setTitle("导入规则") |
||||||
|
.setItems(R.array.import_rule, (dialog, which) -> { |
||||||
|
if (which == 0) { |
||||||
|
String text = ClipBoardUtil.paste(this); |
||||||
|
if (!isEmpty(text)) { |
||||||
|
importDataS(text); |
||||||
|
} else { |
||||||
|
ToastUtils.showError("剪切板内容为空,导入失败"); |
||||||
|
} |
||||||
|
} else { |
||||||
|
ToastUtils.showInfo("请选择内容替换规则JSON文件"); |
||||||
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT); |
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE); |
||||||
|
intent.setType("application/json"); |
||||||
|
startActivityForResult(intent, APPCONST.REQUEST_IMPORT_REPLACE_RULE); |
||||||
|
} |
||||||
|
}).show(); |
||||||
|
break; |
||||||
|
case R.id.action_export: |
||||||
|
if (mReplaceRules == null || mReplaceRules.size() == 0){ |
||||||
|
ToastUtils.showWarring("当前没有任何规则,无法导出!"); |
||||||
|
return true; |
||||||
|
} |
||||||
|
if (FileUtils.writeText(GsonExtensionsKt.getGSON().toJson(mReplaceRules), |
||||||
|
FileUtils.getFile(APPCONST.FILE_DIR + "ReplaceRule.json"))) { |
||||||
|
DialogCreator.createTipDialog(this, |
||||||
|
"内容替换规则导出成功,导出位置:" + APPCONST.FILE_DIR + "ReplaceRule.json"); |
||||||
|
} |
||||||
|
break; |
||||||
|
case R.id.action_reverse: |
||||||
|
for (ReplaceRuleBean ruleBean : mReplaceRules) { |
||||||
|
ruleBean.setEnable(!ruleBean.getEnable()); |
||||||
|
} |
||||||
|
ReplaceRuleManager.addDataS(mReplaceRules); |
||||||
|
mAdapter.notifyDataSetChanged(); |
||||||
|
refreshUI(); |
||||||
|
break; |
||||||
|
case R.id.action_delete: |
||||||
|
DialogCreator.createCommonDialog(this, "删除禁用规则", |
||||||
|
"确定要删除所有禁用规则吗?", true, |
||||||
|
(dialog, which) -> { |
||||||
|
List<ReplaceRuleBean> ruleBeans = new ArrayList<>(); |
||||||
|
for (ReplaceRuleBean ruleBean : mReplaceRules) { |
||||||
|
if (!ruleBean.getEnable()) { |
||||||
|
ruleBeans.add(ruleBean); |
||||||
|
} |
||||||
|
} |
||||||
|
ReplaceRuleManager.delDataS(ruleBeans); |
||||||
|
mReplaceRules.removeAll(ruleBeans); |
||||||
|
mAdapter.removeItems(ruleBeans); |
||||||
|
ToastUtils.showSuccess("禁用规则删除成功"); |
||||||
|
setUpBarTitle(); |
||||||
|
refreshUI(); |
||||||
|
}, null); |
||||||
|
break; |
||||||
|
} |
||||||
|
return super.onOptionsItemSelected(item); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { |
||||||
|
if (resultCode == RESULT_OK) { |
||||||
|
if (requestCode == APPCONST.REQUEST_IMPORT_REPLACE_RULE) { |
||||||
|
String path = getPath(this, data.getData()); |
||||||
|
String json = FileUtils.readText(path); |
||||||
|
if (!isEmpty(json)) { |
||||||
|
importDataS(json); |
||||||
|
} else { |
||||||
|
ToastUtils.showError("文件读取失败"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
super.onActivityResult(requestCode, resultCode, data); |
||||||
|
} |
||||||
|
|
||||||
|
public void importDataS(String text) { |
||||||
|
Observable<Boolean> observable = ReplaceRuleManager.importReplaceRule(text); |
||||||
|
if (observable != null) { |
||||||
|
observable.subscribe(new MyObserver<Boolean>() { |
||||||
|
@Override |
||||||
|
public void onNext(Boolean aBoolean) { |
||||||
|
if (aBoolean) { |
||||||
|
mReplaceRules = ReplaceRuleManager.getAllRules(); |
||||||
|
mAdapter.refreshItems(mReplaceRules); |
||||||
|
setUpBarTitle(); |
||||||
|
refreshUI(); |
||||||
|
ToastUtils.showSuccess("内容替换规则导入成功"); |
||||||
|
} else { |
||||||
|
ToastUtils.showError("格式不对"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onError(Throwable e) { |
||||||
|
ToastUtils.showError("格式不对"); |
||||||
|
} |
||||||
|
}); |
||||||
|
} else { |
||||||
|
ToastUtils.showError("导入失败"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void refreshUI() { |
||||||
|
Intent result = new Intent(); |
||||||
|
result.putExtra(APPCONST.RESULT_NEED_REFRESH, true); |
||||||
|
setResult(AppCompatActivity.RESULT_OK, result); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
package xyz.fycz.myreader.ui.adapter; |
||||||
|
|
||||||
|
import android.app.Activity; |
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.base.adapter.BaseListAdapter; |
||||||
|
import xyz.fycz.myreader.base.adapter.IViewHolder; |
||||||
|
import xyz.fycz.myreader.greendao.entity.ReplaceRuleBean; |
||||||
|
import xyz.fycz.myreader.ui.adapter.holder.ReplaceRuleHolder; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2021/1/19 9:51 |
||||||
|
*/ |
||||||
|
public class ReplaceRuleAdapter extends BaseListAdapter<ReplaceRuleBean> { |
||||||
|
private AppCompatActivity activity; |
||||||
|
private OnDeleteListener onDeleteListener; |
||||||
|
|
||||||
|
public ReplaceRuleAdapter(AppCompatActivity activity, OnDeleteListener onDeleteListener) { |
||||||
|
this.activity = activity; |
||||||
|
this.onDeleteListener = onDeleteListener; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected IViewHolder<ReplaceRuleBean> createViewHolder(int viewType) { |
||||||
|
return new ReplaceRuleHolder(activity, onDeleteListener); |
||||||
|
} |
||||||
|
|
||||||
|
public void removeItem2(ReplaceRuleBean ruleBean){ |
||||||
|
mList.remove(ruleBean); |
||||||
|
} |
||||||
|
|
||||||
|
public interface OnDeleteListener{ |
||||||
|
void success(int which, ReplaceRuleBean ruleBean); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,144 @@ |
|||||||
|
package xyz.fycz.myreader.ui.adapter.holder; |
||||||
|
|
||||||
|
import android.app.Activity; |
||||||
|
import android.content.ClipData; |
||||||
|
import android.content.ClipboardManager; |
||||||
|
import android.content.Context; |
||||||
|
import android.content.Intent; |
||||||
|
import android.widget.Button; |
||||||
|
import android.widget.RelativeLayout; |
||||||
|
import android.widget.TextView; |
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity; |
||||||
|
|
||||||
|
import com.mcxtzhang.swipemenulib.SwipeMenuLayout; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import io.reactivex.Observable; |
||||||
|
import io.reactivex.ObservableOnSubscribe; |
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers; |
||||||
|
import io.reactivex.annotations.NonNull; |
||||||
|
import io.reactivex.schedulers.Schedulers; |
||||||
|
import xyz.fycz.myreader.R; |
||||||
|
import xyz.fycz.myreader.base.adapter.ViewHolderImpl; |
||||||
|
import xyz.fycz.myreader.base.observer.MyObserver; |
||||||
|
import xyz.fycz.myreader.base.observer.MySingleObserver; |
||||||
|
import xyz.fycz.myreader.common.APPCONST; |
||||||
|
import xyz.fycz.myreader.greendao.entity.ReplaceRuleBean; |
||||||
|
import xyz.fycz.myreader.model.ReplaceRuleManager; |
||||||
|
import xyz.fycz.myreader.ui.adapter.ReplaceRuleAdapter; |
||||||
|
import xyz.fycz.myreader.ui.dialog.ReplaceDialog; |
||||||
|
import xyz.fycz.myreader.util.ShareUtils; |
||||||
|
import xyz.fycz.myreader.util.ToastUtils; |
||||||
|
import xyz.fycz.myreader.util.utils.GsonExtensionsKt; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2021/1/19 9:54 |
||||||
|
*/ |
||||||
|
public class ReplaceRuleHolder extends ViewHolderImpl<ReplaceRuleBean> { |
||||||
|
private RelativeLayout rlContent; |
||||||
|
private TextView tvRuleSummary; |
||||||
|
private Button btBan; |
||||||
|
private Button btShare; |
||||||
|
private Button btDelete; |
||||||
|
private AppCompatActivity activity; |
||||||
|
private ReplaceRuleAdapter.OnDeleteListener onDeleteListener; |
||||||
|
|
||||||
|
public ReplaceRuleHolder(AppCompatActivity activity, ReplaceRuleAdapter.OnDeleteListener onDeleteListener) { |
||||||
|
this.activity = activity; |
||||||
|
this.onDeleteListener = onDeleteListener; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected int getItemLayoutId() { |
||||||
|
return R.layout.item_replace_rule; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initView() { |
||||||
|
rlContent = findById(R.id.rl_content); |
||||||
|
tvRuleSummary = findById(R.id.tv_rule_summary); |
||||||
|
btBan = findById(R.id.bt_ban); |
||||||
|
btShare = findById(R.id.bt_share); |
||||||
|
btDelete = findById(R.id.btnDelete); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onBind(ReplaceRuleBean data, int pos) { |
||||||
|
banOrUse(data); |
||||||
|
|
||||||
|
rlContent.setOnClickListener(v -> { |
||||||
|
ReplaceDialog replaceDialog = new ReplaceDialog(activity, data, |
||||||
|
() -> { |
||||||
|
banOrUse(data); |
||||||
|
ToastUtils.showSuccess("内容替换规则修改成功!"); |
||||||
|
refreshUI(); |
||||||
|
}); |
||||||
|
replaceDialog.show(activity.getSupportFragmentManager(), ""); |
||||||
|
}); |
||||||
|
|
||||||
|
btBan.setOnClickListener(v -> { |
||||||
|
((SwipeMenuLayout) getItemView()).smoothClose(); |
||||||
|
data.setEnable(!data.getEnable()); |
||||||
|
ReplaceRuleManager.saveData(data) |
||||||
|
.subscribe(new MySingleObserver<Boolean>() { |
||||||
|
@Override |
||||||
|
public void onSuccess(@NonNull Boolean aBoolean) { |
||||||
|
if (aBoolean) { |
||||||
|
banOrUse(data); |
||||||
|
refreshUI(); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
||||||
|
btShare.setOnClickListener(v -> { |
||||||
|
((SwipeMenuLayout) getItemView()).smoothClose(); |
||||||
|
List<ReplaceRuleBean> shareRuleBean = new ArrayList<>(); |
||||||
|
shareRuleBean.add(data); |
||||||
|
ShareUtils.share(activity, GsonExtensionsKt.getGSON().toJson(shareRuleBean)); |
||||||
|
}); |
||||||
|
btDelete.setOnClickListener(v -> { |
||||||
|
((SwipeMenuLayout) getItemView()).smoothClose(); |
||||||
|
Observable.create((ObservableOnSubscribe<Boolean>) e -> { |
||||||
|
ReplaceRuleManager.delData(data); |
||||||
|
e.onNext(true); |
||||||
|
}).subscribeOn(Schedulers.io()) |
||||||
|
.observeOn(AndroidSchedulers.mainThread()) |
||||||
|
.subscribe(new MyObserver<Boolean>() { |
||||||
|
@Override |
||||||
|
public void onNext(Boolean aBoolean) { |
||||||
|
onDeleteListener.success(pos, data); |
||||||
|
refreshUI(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onError(Throwable e) { |
||||||
|
ToastUtils.showError("删除失败"); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private void banOrUse(ReplaceRuleBean data){ |
||||||
|
if (data.getEnable()) { |
||||||
|
tvRuleSummary.setTextColor(getContext().getResources().getColor(R.color.textPrimary)); |
||||||
|
tvRuleSummary.setText(String.format("%s->%s", data.getRegex(), data.getReplacement())); |
||||||
|
btBan.setText(getContext().getString(R.string.ban)); |
||||||
|
} else { |
||||||
|
tvRuleSummary.setTextColor(getContext().getResources().getColor(R.color.textSecondary)); |
||||||
|
tvRuleSummary.setText(String.format("(禁用中)%s->%s", data.getRegex(), data.getReplacement())); |
||||||
|
btBan.setText(R.string.enable_use); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void refreshUI(){ |
||||||
|
Intent result = new Intent(); |
||||||
|
result.putExtra(APPCONST.RESULT_NEED_REFRESH, true); |
||||||
|
activity.setResult(AppCompatActivity.RESULT_OK, result); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,218 @@ |
|||||||
|
package xyz.fycz.myreader.ui.dialog; |
||||||
|
|
||||||
|
import android.app.Activity; |
||||||
|
import android.content.DialogInterface; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.view.LayoutInflater; |
||||||
|
import android.view.View; |
||||||
|
import android.view.ViewGroup; |
||||||
|
import android.widget.Button; |
||||||
|
import android.widget.CheckBox; |
||||||
|
import android.widget.EditText; |
||||||
|
import android.widget.TextView; |
||||||
|
|
||||||
|
import androidx.annotation.NonNull; |
||||||
|
import androidx.annotation.Nullable; |
||||||
|
import androidx.appcompat.widget.AppCompatEditText; |
||||||
|
import androidx.fragment.app.DialogFragment; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.R; |
||||||
|
import xyz.fycz.myreader.base.observer.MySingleObserver; |
||||||
|
import xyz.fycz.myreader.enums.BookSource; |
||||||
|
import xyz.fycz.myreader.greendao.entity.Book; |
||||||
|
import xyz.fycz.myreader.greendao.entity.ReplaceRuleBean; |
||||||
|
import xyz.fycz.myreader.greendao.service.BookService; |
||||||
|
import xyz.fycz.myreader.model.ReplaceRuleManager; |
||||||
|
import xyz.fycz.myreader.util.SharedPreUtils; |
||||||
|
import xyz.fycz.myreader.util.ToastUtils; |
||||||
|
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2021/1/18 20:04 |
||||||
|
*/ |
||||||
|
public class ReplaceDialog extends DialogFragment { |
||||||
|
private ReplaceRuleBean replaceRule; |
||||||
|
private Activity activity; |
||||||
|
private OnSaveReplaceRule onSaveReplaceRule; |
||||||
|
private EditText etRuleDesc; |
||||||
|
private EditText etRuleOld; |
||||||
|
private EditText etRuleNew; |
||||||
|
private EditText etRuleSource; |
||||||
|
private EditText etRuleBook; |
||||||
|
private CheckBox cbUseRegex; |
||||||
|
private Button btSelectSource; |
||||||
|
private Button btSelectBook; |
||||||
|
private TextView tvConfirm; |
||||||
|
private TextView tvCancel; |
||||||
|
|
||||||
|
public ReplaceDialog(Activity activity, ReplaceRuleBean replaceRule, OnSaveReplaceRule onSaveReplaceRule) { |
||||||
|
this.activity = activity; |
||||||
|
this.replaceRule = replaceRule; |
||||||
|
this.onSaveReplaceRule = onSaveReplaceRule; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) { |
||||||
|
super.onCreate(savedInstanceState); |
||||||
|
setStyle(DialogFragment.STYLE_NORMAL, R.style.alertDialogTheme); |
||||||
|
} |
||||||
|
|
||||||
|
@Nullable |
||||||
|
@Override |
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { |
||||||
|
View v = inflater.inflate(R.layout.dialog_replace, container, false); |
||||||
|
etRuleDesc = v.findViewById(R.id.et_rule_desc); |
||||||
|
etRuleOld = v.findViewById(R.id.et_rule_old); |
||||||
|
etRuleNew = v.findViewById(R.id.et_rule_new); |
||||||
|
etRuleSource = v.findViewById(R.id.et_rule_source); |
||||||
|
etRuleBook = v.findViewById(R.id.et_rule_book); |
||||||
|
cbUseRegex = v.findViewById(R.id.cb_use_regex); |
||||||
|
btSelectSource = v.findViewById(R.id.bt_select_source); |
||||||
|
btSelectBook = v.findViewById(R.id.bt_select_book); |
||||||
|
tvCancel = v.findViewById(R.id.tv_cancel); |
||||||
|
tvConfirm = v.findViewById(R.id.tv_confirm); |
||||||
|
|
||||||
|
etRuleDesc.setText(replaceRule.getReplaceSummary()); |
||||||
|
etRuleOld.setText(replaceRule.getRegex()); |
||||||
|
cbUseRegex.setChecked(replaceRule.getIsRegex()); |
||||||
|
etRuleNew.setText(replaceRule.getReplacement()); |
||||||
|
String[] useTo = replaceRule.getUseTo().split(";"); |
||||||
|
etRuleSource.setText(useTo.length > 0 ?useTo[0] : ""); |
||||||
|
etRuleBook.setText(useTo.length > 1 ? useTo[1] : ""); |
||||||
|
btSelectSource.setOnClickListener(v1 -> selectSource()); |
||||||
|
btSelectBook.setOnClickListener(v1 -> selectBook()); |
||||||
|
|
||||||
|
tvConfirm.setOnClickListener(v1 -> { |
||||||
|
replaceRule.setReplaceSummary(etRuleDesc.getText().toString()); |
||||||
|
replaceRule.setRegex(etRuleOld.getText().toString()); |
||||||
|
replaceRule.setIsRegex(cbUseRegex.isChecked()); |
||||||
|
replaceRule.setReplacement(etRuleNew.getText().toString()); |
||||||
|
replaceRule.setUseTo(String.format("%s;%s", etRuleSource.getText().toString(), etRuleBook.getText().toString())); |
||||||
|
ReplaceRuleManager.saveData(replaceRule).subscribe(new MySingleObserver<Boolean>() { |
||||||
|
@Override |
||||||
|
public void onSuccess(@NonNull Boolean aBoolean) { |
||||||
|
onSaveReplaceRule.success(); |
||||||
|
dismiss(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onError(Throwable e) { |
||||||
|
ToastUtils.showError("发生错误\n" + e.getLocalizedMessage()); |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
||||||
|
tvCancel.setOnClickListener(v1 -> dismiss()); |
||||||
|
return v; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 选择书源 |
||||||
|
*/ |
||||||
|
private void selectSource(){ |
||||||
|
List<String> mSources = ReadCrawlerUtil.getAllSources(); |
||||||
|
CharSequence[] mSourcesName = new CharSequence[mSources.size()]; |
||||||
|
HashMap<CharSequence, Boolean> mSelectSources = new LinkedHashMap<>(); |
||||||
|
boolean[] isSelects = new boolean[mSources.size()]; |
||||||
|
int sSourceCount = 0; |
||||||
|
int i = 0; |
||||||
|
|
||||||
|
String selectSource = etRuleSource.getText().toString(); |
||||||
|
|
||||||
|
for (CharSequence sourceName : mSources) { |
||||||
|
mSourcesName[i] = sourceName; |
||||||
|
String source = BookSource.getFromName(String.valueOf(sourceName)); |
||||||
|
boolean isSelect = selectSource.contains(source); |
||||||
|
if (isSelect) sSourceCount++; |
||||||
|
mSelectSources.put(mSourcesName[i], isSelect); |
||||||
|
isSelects[i++] = isSelect; |
||||||
|
} |
||||||
|
|
||||||
|
new MultiChoiceDialog().create(activity, "选择书源", |
||||||
|
mSourcesName, isSelects, sSourceCount, (dialog, which) -> { |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
for (CharSequence sourceName : mSelectSources.keySet()) { |
||||||
|
if (mSelectSources.get(sourceName)) { |
||||||
|
sb.append(BookSource.getFromName(String.valueOf(sourceName))); |
||||||
|
sb.append(","); |
||||||
|
} |
||||||
|
} |
||||||
|
if (sb.lastIndexOf(",") >= 0) sb.deleteCharAt(sb.lastIndexOf(",")); |
||||||
|
etRuleSource.setText(sb.toString()); |
||||||
|
}, null, new DialogCreator.OnMultiDialogListener() { |
||||||
|
@Override |
||||||
|
public void onItemClick(DialogInterface dialog, int which, boolean isChecked) { |
||||||
|
mSelectSources.put(mSourcesName[which], isChecked); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onSelectAll(boolean isSelectAll) { |
||||||
|
for (CharSequence sourceName : mSelectSources.keySet()) { |
||||||
|
mSelectSources.put(sourceName, isSelectAll); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 选择书籍 |
||||||
|
*/ |
||||||
|
private void selectBook(){ |
||||||
|
List<Book> mBooks = BookService.getInstance().getAllBooksNoHide(); |
||||||
|
HashMap<CharSequence, Boolean> mSelectBooks = new LinkedHashMap<>(); |
||||||
|
|
||||||
|
if (mBooks == null || mBooks.size() == 0){ |
||||||
|
ToastUtils.showWarring("当前没有任何书籍!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
String isSelect = etRuleBook.getText().toString(); |
||||||
|
|
||||||
|
CharSequence[] mBooksName = new CharSequence[mBooks.size()]; |
||||||
|
boolean[] isSelects = new boolean[mBooks.size()]; |
||||||
|
int sBookCount = 0; |
||||||
|
|
||||||
|
for (int i = 0; i < mBooks.size(); i++) { |
||||||
|
Book book = mBooks.get(i); |
||||||
|
mBooksName[i] = book.getName() + "-" + book.getAuthor(); |
||||||
|
isSelects[i] = isSelect.contains(book.getName()); |
||||||
|
if (isSelects[i]) { |
||||||
|
mSelectBooks.put(mBooksName[i], true); |
||||||
|
sBookCount++; |
||||||
|
}else { |
||||||
|
mSelectBooks.put(mBooksName[i], false); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
new MultiChoiceDialog().create(activity, "选择书籍", |
||||||
|
mBooksName, isSelects, sBookCount, (dialog, which) -> { |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
for (CharSequence bookName : mSelectBooks.keySet()) { |
||||||
|
if (mSelectBooks.get(bookName)) { |
||||||
|
sb.append(bookName); |
||||||
|
sb.append(","); |
||||||
|
} |
||||||
|
} |
||||||
|
if (sb.lastIndexOf(",") >= 0) sb.deleteCharAt(sb.lastIndexOf(",")); |
||||||
|
etRuleBook.setText(sb.toString()); |
||||||
|
}, null, new DialogCreator.OnMultiDialogListener() { |
||||||
|
@Override |
||||||
|
public void onItemClick(DialogInterface dialog, int which, boolean isChecked) { |
||||||
|
mSelectBooks.put(mBooksName[which], isChecked); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onSelectAll(boolean isSelectAll) { |
||||||
|
for (CharSequence bookName : mSelectBooks.keySet()) { |
||||||
|
mSelectBooks.put(bookName, isSelectAll); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
public interface OnSaveReplaceRule{ |
||||||
|
void success(); |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,68 @@ |
|||||||
|
package xyz.fycz.myreader.util.utils; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2021/1/19 14:30 |
||||||
|
*/ |
||||||
|
|
||||||
|
import android.content.ClipData; |
||||||
|
import android.content.ClipboardManager; |
||||||
|
import android.content.Context; |
||||||
|
import android.text.TextUtils; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.application.MyApplication; |
||||||
|
import xyz.fycz.myreader.util.ToastUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* 剪切板读写工具 |
||||||
|
*/ |
||||||
|
public class ClipBoardUtil { |
||||||
|
/** |
||||||
|
* 获取剪切板内容 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String paste(Context context) { |
||||||
|
ClipboardManager manager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); |
||||||
|
if (manager != null) { |
||||||
|
if (manager.hasPrimaryClip() && manager.getPrimaryClip().getItemCount() > 0) { |
||||||
|
CharSequence addedText = manager.getPrimaryClip().getItemAt(0).getText(); |
||||||
|
String addedTextString = String.valueOf(addedText); |
||||||
|
if (!TextUtils.isEmpty(addedTextString)) { |
||||||
|
return addedTextString; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 写入剪切板 |
||||||
|
* @param text |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static boolean write(Context context, String text){ |
||||||
|
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); |
||||||
|
ClipData clipData = ClipData.newPlainText(null, text); |
||||||
|
if (clipboard != null) { |
||||||
|
clipboard.setPrimaryClip(clipData); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 清空剪切板 |
||||||
|
*/ |
||||||
|
public static void clear(Context context) { |
||||||
|
ClipboardManager manager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); |
||||||
|
if (manager != null) { |
||||||
|
try { |
||||||
|
manager.setPrimaryClip(manager.getPrimaryClip()); |
||||||
|
manager.setPrimaryClip(ClipData.newPlainText("", "")); |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,642 @@ |
|||||||
|
package xyz.fycz.myreader.widget; |
||||||
|
|
||||||
|
import android.app.Activity; |
||||||
|
import android.content.Context; |
||||||
|
import android.content.res.ColorStateList; |
||||||
|
import android.content.res.Resources; |
||||||
|
import android.graphics.Canvas; |
||||||
|
import android.graphics.Color; |
||||||
|
import android.graphics.ColorFilter; |
||||||
|
import android.graphics.Paint; |
||||||
|
import android.graphics.Path; |
||||||
|
import android.graphics.PixelFormat; |
||||||
|
import android.graphics.drawable.BitmapDrawable; |
||||||
|
import android.graphics.drawable.Drawable; |
||||||
|
import android.graphics.drawable.GradientDrawable; |
||||||
|
import android.graphics.drawable.StateListDrawable; |
||||||
|
import android.util.Log; |
||||||
|
import android.util.TypedValue; |
||||||
|
import android.view.Gravity; |
||||||
|
import android.view.View; |
||||||
|
import android.view.ViewGroup; |
||||||
|
import android.view.ViewParent; |
||||||
|
import android.widget.ImageView; |
||||||
|
import android.widget.LinearLayout; |
||||||
|
import android.widget.PopupWindow; |
||||||
|
import android.widget.TextView; |
||||||
|
|
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 仿QQ长按气泡弹窗 |
||||||
|
* 作者:pixiaozhi |
||||||
|
* 时间:19/05/31. |
||||||
|
*/ |
||||||
|
public class BubblePopupView { |
||||||
|
|
||||||
|
private static final boolean DEFAULT_SHOW_BOTTOM = false; |
||||||
|
private static final boolean DEFAULT_SHOW_TOUCH_LOCATION = false; |
||||||
|
private static final boolean DEFAULT_FOCUSABLE = true; |
||||||
|
private static final int DEFAULT_NORMAL_TEXT_COLOR = Color.WHITE; |
||||||
|
private static final int DEFAULT_PRESSED_TEXT_COLOR = Color.WHITE; |
||||||
|
private static final float DEFAULT_TEXT_SIZE_DP = 14; |
||||||
|
private static final float DEFAULT_TEXT_PADDING_LEFT_DP = 10.0f; |
||||||
|
private static final float DEFAULT_TEXT_PADDING_TOP_DP = 5.0f; |
||||||
|
private static final float DEFAULT_TEXT_PADDING_RIGHT_DP = 10.0f; |
||||||
|
private static final float DEFAULT_TEXT_PADDING_BOTTOM_DP = 5.0f; |
||||||
|
private static final int DEFAULT_NORMAL_BACKGROUND_COLOR = 0xCC000000; |
||||||
|
private static final int DEFAULT_PRESSED_BACKGROUND_COLOR = 0xE7777777; |
||||||
|
private static final int DEFAULT_BACKGROUND_RADIUS_DP = 8; |
||||||
|
private static final int DEFAULT_DIVIDER_COLOR = 0x9AFFFFFF; |
||||||
|
private static final float DEFAULT_DIVIDER_WIDTH_DP = 0.5f; |
||||||
|
private static final float DEFAULT_DIVIDER_HEIGHT_DP = 16.0f; |
||||||
|
private static final float DEFAULT_NAVIGATION_BAR_HEIGHT = 0f; |
||||||
|
|
||||||
|
private Context mContext; |
||||||
|
private PopupWindow mPopupWindow; |
||||||
|
private View mAnchorView; |
||||||
|
private View mContextView; |
||||||
|
private View mIndicatorView; |
||||||
|
private List<String> mPopupItemList; |
||||||
|
private PopupListListener mPopupListListener; |
||||||
|
private int mContextPosition; |
||||||
|
private StateListDrawable mLeftItemBackground; |
||||||
|
private StateListDrawable mRightItemBackground; |
||||||
|
private StateListDrawable mCornerItemBackground; |
||||||
|
private ColorStateList mTextColorStateList; |
||||||
|
private GradientDrawable mCornerBackground; |
||||||
|
//指示器属性
|
||||||
|
private int mIndicatorWidth; |
||||||
|
private int mIndicatorHeight; |
||||||
|
//PopupWindow属性
|
||||||
|
private int mPopupWindowWidth; |
||||||
|
private int mPopupWindowHeight; |
||||||
|
//文本属性
|
||||||
|
private int mNormalTextColor; |
||||||
|
private int mPressedTextColor; |
||||||
|
private float mTextSize; |
||||||
|
private int mTextPaddingLeft; |
||||||
|
private int mTextPaddingTop; |
||||||
|
private int mTextPaddingRight; |
||||||
|
private int mTextPaddingBottom; |
||||||
|
private int mNormalBackgroundColor; |
||||||
|
private int mPressedBackgroundColor; |
||||||
|
private int mBackgroundCornerRadius; |
||||||
|
//分割线属性
|
||||||
|
private int mDividerColor; |
||||||
|
private int mDividerWidth; |
||||||
|
private int mDividerHeight; |
||||||
|
//是否显示在下方
|
||||||
|
private boolean mIsShowBottom; |
||||||
|
//是否跟随手指显示
|
||||||
|
private boolean mIsShowTouchLocation; |
||||||
|
//倒转高度,当落下位置比这个值小时,气泡显示在下方
|
||||||
|
private float mReversalHeight; |
||||||
|
//popWindow是否聚焦,默认是
|
||||||
|
private boolean mIsFocusable; |
||||||
|
|
||||||
|
public BubblePopupView(Context context) { |
||||||
|
this.mContext = context; |
||||||
|
this.mIsShowBottom = DEFAULT_SHOW_BOTTOM; |
||||||
|
this.mIsShowTouchLocation = DEFAULT_SHOW_TOUCH_LOCATION; |
||||||
|
this.mIsFocusable = DEFAULT_FOCUSABLE; |
||||||
|
this.mReversalHeight = dp2px(DEFAULT_NAVIGATION_BAR_HEIGHT); |
||||||
|
this.mNormalTextColor = DEFAULT_NORMAL_TEXT_COLOR; |
||||||
|
this.mPressedTextColor = DEFAULT_PRESSED_TEXT_COLOR; |
||||||
|
this.mTextSize = dp2px(DEFAULT_TEXT_SIZE_DP); |
||||||
|
this.mTextPaddingLeft = dp2px(DEFAULT_TEXT_PADDING_LEFT_DP); |
||||||
|
this.mTextPaddingTop = dp2px(DEFAULT_TEXT_PADDING_TOP_DP); |
||||||
|
this.mTextPaddingRight = dp2px(DEFAULT_TEXT_PADDING_RIGHT_DP); |
||||||
|
this.mTextPaddingBottom = dp2px(DEFAULT_TEXT_PADDING_BOTTOM_DP); |
||||||
|
this.mNormalBackgroundColor = DEFAULT_NORMAL_BACKGROUND_COLOR; |
||||||
|
this.mPressedBackgroundColor = DEFAULT_PRESSED_BACKGROUND_COLOR; |
||||||
|
this.mBackgroundCornerRadius = dp2px(DEFAULT_BACKGROUND_RADIUS_DP); |
||||||
|
this.mDividerColor = DEFAULT_DIVIDER_COLOR; |
||||||
|
this.mDividerWidth = dp2px(DEFAULT_DIVIDER_WIDTH_DP); |
||||||
|
this.mDividerHeight = dp2px(DEFAULT_DIVIDER_HEIGHT_DP); |
||||||
|
this.mIndicatorView = getDefaultIndicatorView(mContext); |
||||||
|
refreshBackgroundOrRadiusStateList(); |
||||||
|
refreshTextColorStateList(mPressedTextColor, mNormalTextColor); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 以气泡样式显示弹出窗口 |
||||||
|
* |
||||||
|
* @param anchorView 要固定弹出窗口的视图 |
||||||
|
* @param contextPosition 上下文位置,当是列表时用于记录Position |
||||||
|
* @param rawX 原始X坐标 |
||||||
|
* @param rawY 原始Y坐标 |
||||||
|
* @param popupItemList 弹出菜单列表 |
||||||
|
* @param popupListListener 监听器 |
||||||
|
*/ |
||||||
|
public void showPopupListWindow(View anchorView, int contextPosition, float rawX, float rawY, |
||||||
|
List<String> popupItemList, PopupListListener popupListListener) { |
||||||
|
mAnchorView = anchorView; |
||||||
|
mContextPosition = contextPosition; |
||||||
|
mPopupItemList = popupItemList; |
||||||
|
mPopupListListener = popupListListener; |
||||||
|
mPopupWindow = null; |
||||||
|
mContextView = anchorView; |
||||||
|
if (mPopupListListener != null |
||||||
|
&& !mPopupListListener.showPopupList(mContextView, mContextView, contextPosition)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
int[] location = new int[2]; |
||||||
|
mAnchorView.getLocationOnScreen(location); |
||||||
|
// LogUtil.e("rawX:" + rawX + ",rawY:" + rawY + ",location[0]:" + location[0] + ",location[1]" + location[1]);
|
||||||
|
if (mIsShowTouchLocation) { |
||||||
|
showPopupListWindow(rawX - location[0], rawY - location[1]); |
||||||
|
} else { |
||||||
|
Log.e("navigationBarHeight:", mReversalHeight + rawY + ",rawY:" + rawY); |
||||||
|
if (mReversalHeight > rawY) { |
||||||
|
mIsShowBottom = true; |
||||||
|
showPopupListWindow(mAnchorView.getWidth() / 2f, mAnchorView.getHeight()); |
||||||
|
} else { |
||||||
|
mIsShowBottom = false; |
||||||
|
showPopupListWindow(mAnchorView.getWidth() / 2f, 0); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建布局和显示 |
||||||
|
*/ |
||||||
|
private void showPopupListWindow(float offsetX, float offsetY) { |
||||||
|
if (mContext instanceof Activity && ((Activity) mContext).isFinishing()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (mPopupWindow == null) { |
||||||
|
//创建根布局
|
||||||
|
LinearLayout contentView = new LinearLayout(mContext); |
||||||
|
contentView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); |
||||||
|
contentView.setOrientation(LinearLayout.VERTICAL); |
||||||
|
//创建list布局
|
||||||
|
LinearLayout popupListContainer = new LinearLayout(mContext); |
||||||
|
popupListContainer.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); |
||||||
|
popupListContainer.setOrientation(LinearLayout.HORIZONTAL); |
||||||
|
popupListContainer.setBackgroundDrawable(mCornerBackground); |
||||||
|
|
||||||
|
//创建指示器
|
||||||
|
if (mIndicatorView != null) { |
||||||
|
LinearLayout.LayoutParams layoutParams; |
||||||
|
if (mIndicatorView.getLayoutParams() == null) { |
||||||
|
layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); |
||||||
|
} else { |
||||||
|
layoutParams = (LinearLayout.LayoutParams) mIndicatorView.getLayoutParams(); |
||||||
|
} |
||||||
|
layoutParams.gravity = Gravity.CENTER; |
||||||
|
mIndicatorView.setLayoutParams(layoutParams); |
||||||
|
ViewParent viewParent = mIndicatorView.getParent(); |
||||||
|
if (viewParent instanceof ViewGroup) { |
||||||
|
((ViewGroup) viewParent).removeView(mIndicatorView); |
||||||
|
} |
||||||
|
|
||||||
|
if (!mIsShowBottom) { |
||||||
|
contentView.addView(popupListContainer); |
||||||
|
contentView.addView(mIndicatorView); |
||||||
|
} else { |
||||||
|
contentView.addView(mIndicatorView); |
||||||
|
contentView.addView(popupListContainer); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//添加list的item
|
||||||
|
for (int i = 0; i < mPopupItemList.size(); i++) { |
||||||
|
TextView textView = new TextView(mContext); |
||||||
|
textView.setTextColor(mTextColorStateList); |
||||||
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); |
||||||
|
textView.setPadding(mTextPaddingLeft, mTextPaddingTop, mTextPaddingRight, mTextPaddingBottom); |
||||||
|
textView.setClickable(true); |
||||||
|
final int finalI = i; |
||||||
|
//设置点击回调
|
||||||
|
textView.setOnClickListener(new View.OnClickListener() { |
||||||
|
@Override |
||||||
|
public void onClick(View v) { |
||||||
|
if (mPopupListListener != null) { |
||||||
|
mPopupListListener.onPopupListClick(mContextView, mContextPosition, finalI); |
||||||
|
hidePopupListWindow(); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
textView.setText(mPopupItemList.get(i)); |
||||||
|
|
||||||
|
//设置item的背景
|
||||||
|
if (mPopupItemList.size() > 1 && i == 0) { |
||||||
|
textView.setBackgroundDrawable(mLeftItemBackground); |
||||||
|
} else if (mPopupItemList.size() > 1 && i == mPopupItemList.size() - 1) { |
||||||
|
textView.setBackgroundDrawable(mRightItemBackground); |
||||||
|
} else if (mPopupItemList.size() == 1) { |
||||||
|
textView.setBackgroundDrawable(mCornerItemBackground); |
||||||
|
} else { |
||||||
|
textView.setBackgroundDrawable(getCenterItemBackground()); |
||||||
|
} |
||||||
|
popupListContainer.addView(textView); |
||||||
|
//设置2个item中的分割线
|
||||||
|
if (mPopupItemList.size() > 1 && i != mPopupItemList.size() - 1) { |
||||||
|
View divider = new View(mContext); |
||||||
|
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(mDividerWidth, mDividerHeight); |
||||||
|
layoutParams.gravity = Gravity.CENTER; |
||||||
|
divider.setLayoutParams(layoutParams); |
||||||
|
divider.setBackgroundColor(mDividerColor); |
||||||
|
popupListContainer.addView(divider); |
||||||
|
} |
||||||
|
} |
||||||
|
if (mPopupWindowWidth == 0) { |
||||||
|
mPopupWindowWidth = getViewWidth(popupListContainer); |
||||||
|
} |
||||||
|
//获取指示器宽高
|
||||||
|
if (mIndicatorView != null && mIndicatorWidth == 0) { |
||||||
|
if (mIndicatorView.getLayoutParams().width > 0) { |
||||||
|
mIndicatorWidth = mIndicatorView.getLayoutParams().width; |
||||||
|
} else { |
||||||
|
mIndicatorWidth = getViewWidth(mIndicatorView); |
||||||
|
} |
||||||
|
} |
||||||
|
if (mIndicatorView != null && mIndicatorHeight == 0) { |
||||||
|
if (mIndicatorView.getLayoutParams().height > 0) { |
||||||
|
mIndicatorHeight = mIndicatorView.getLayoutParams().height; |
||||||
|
} else { |
||||||
|
mIndicatorHeight = getViewHeight(mIndicatorView); |
||||||
|
} |
||||||
|
} |
||||||
|
if (mPopupWindowHeight == 0) { |
||||||
|
mPopupWindowHeight = getViewHeight(popupListContainer) + mIndicatorHeight; |
||||||
|
} |
||||||
|
mPopupWindow = new PopupWindow(contentView, mPopupWindowWidth, mPopupWindowHeight, true); |
||||||
|
mPopupWindow.setTouchable(true); |
||||||
|
mPopupWindow.setFocusable(mIsFocusable); |
||||||
|
mPopupWindow.setBackgroundDrawable(new BitmapDrawable()); |
||||||
|
} |
||||||
|
int[] location = new int[2]; |
||||||
|
mAnchorView.getLocationOnScreen(location); |
||||||
|
if (mIndicatorView != null) { |
||||||
|
float leftTranslationLimit = mIndicatorWidth / 2f + mBackgroundCornerRadius - mPopupWindowWidth / 2f; |
||||||
|
float rightTranslationLimit = mPopupWindowWidth / 2f - mIndicatorWidth / 2f - mBackgroundCornerRadius; |
||||||
|
//获取最大绝对宽度,单位是px
|
||||||
|
float maxWidth = mContext.getResources().getDisplayMetrics().widthPixels; |
||||||
|
//通过setTranslationX改变view的位置,是不改变view的LayoutParams的,也即不改变getLeft等view的信息
|
||||||
|
if (location[0] + offsetX < mPopupWindowWidth / 2f) { |
||||||
|
mIndicatorView.setTranslationX(Math.max(location[0] + offsetX - mPopupWindowWidth / 2f, leftTranslationLimit)); |
||||||
|
} else if (location[0] + offsetX + mPopupWindowWidth / 2f > maxWidth) { |
||||||
|
mIndicatorView.setTranslationX(Math.min(location[0] + offsetX + mPopupWindowWidth / 2f - maxWidth, rightTranslationLimit)); |
||||||
|
} else { |
||||||
|
mIndicatorView.setTranslationX(0); |
||||||
|
} |
||||||
|
} |
||||||
|
if (!mPopupWindow.isShowing()) { |
||||||
|
int x = (int) (location[0] + offsetX - mPopupWindowWidth / 2f + 0.5f); |
||||||
|
int y = mIsShowBottom ? (int) (location[1] + offsetY + 0.5f) : (int) (location[1] + offsetY - mPopupWindowHeight + 0.5f); |
||||||
|
mPopupWindow.showAtLocation(mAnchorView, Gravity.NO_GRAVITY, x, y); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 刷新背景或附加状态列表 |
||||||
|
*/ |
||||||
|
private void refreshBackgroundOrRadiusStateList() { |
||||||
|
// left
|
||||||
|
GradientDrawable leftItemPressedDrawable = new GradientDrawable(); |
||||||
|
leftItemPressedDrawable.setColor(mPressedBackgroundColor); |
||||||
|
leftItemPressedDrawable.setCornerRadii(new float[]{ |
||||||
|
mBackgroundCornerRadius, mBackgroundCornerRadius, |
||||||
|
0, 0, |
||||||
|
0, 0, |
||||||
|
mBackgroundCornerRadius, mBackgroundCornerRadius}); |
||||||
|
GradientDrawable leftItemNormalDrawable = new GradientDrawable(); |
||||||
|
leftItemNormalDrawable.setColor(Color.TRANSPARENT); |
||||||
|
leftItemNormalDrawable.setCornerRadii(new float[]{ |
||||||
|
mBackgroundCornerRadius, mBackgroundCornerRadius, |
||||||
|
0, 0, |
||||||
|
0, 0, |
||||||
|
mBackgroundCornerRadius, mBackgroundCornerRadius}); |
||||||
|
mLeftItemBackground = new StateListDrawable(); |
||||||
|
mLeftItemBackground.addState(new int[]{android.R.attr.state_pressed}, leftItemPressedDrawable); |
||||||
|
mLeftItemBackground.addState(new int[]{}, leftItemNormalDrawable); |
||||||
|
// right
|
||||||
|
GradientDrawable rightItemPressedDrawable = new GradientDrawable(); |
||||||
|
rightItemPressedDrawable.setColor(mPressedBackgroundColor); |
||||||
|
rightItemPressedDrawable.setCornerRadii(new float[]{ |
||||||
|
0, 0, |
||||||
|
mBackgroundCornerRadius, mBackgroundCornerRadius, |
||||||
|
mBackgroundCornerRadius, mBackgroundCornerRadius, |
||||||
|
0, 0}); |
||||||
|
GradientDrawable rightItemNormalDrawable = new GradientDrawable(); |
||||||
|
rightItemNormalDrawable.setColor(Color.TRANSPARENT); |
||||||
|
rightItemNormalDrawable.setCornerRadii(new float[]{ |
||||||
|
0, 0, |
||||||
|
mBackgroundCornerRadius, mBackgroundCornerRadius, |
||||||
|
mBackgroundCornerRadius, mBackgroundCornerRadius, |
||||||
|
0, 0}); |
||||||
|
mRightItemBackground = new StateListDrawable(); |
||||||
|
mRightItemBackground.addState(new int[]{android.R.attr.state_pressed}, rightItemPressedDrawable); |
||||||
|
mRightItemBackground.addState(new int[]{}, rightItemNormalDrawable); |
||||||
|
// corner
|
||||||
|
GradientDrawable cornerItemPressedDrawable = new GradientDrawable(); |
||||||
|
cornerItemPressedDrawable.setColor(mPressedBackgroundColor); |
||||||
|
cornerItemPressedDrawable.setCornerRadius(mBackgroundCornerRadius); |
||||||
|
GradientDrawable cornerItemNormalDrawable = new GradientDrawable(); |
||||||
|
cornerItemNormalDrawable.setColor(Color.TRANSPARENT); |
||||||
|
cornerItemNormalDrawable.setCornerRadius(mBackgroundCornerRadius); |
||||||
|
mCornerItemBackground = new StateListDrawable(); |
||||||
|
mCornerItemBackground.addState(new int[]{android.R.attr.state_pressed}, cornerItemPressedDrawable); |
||||||
|
mCornerItemBackground.addState(new int[]{}, cornerItemNormalDrawable); |
||||||
|
mCornerBackground = new GradientDrawable(); |
||||||
|
mCornerBackground.setColor(mNormalBackgroundColor); |
||||||
|
mCornerBackground.setCornerRadius(mBackgroundCornerRadius); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取中心item背景 |
||||||
|
*/ |
||||||
|
private StateListDrawable getCenterItemBackground() { |
||||||
|
StateListDrawable centerItemBackground = new StateListDrawable(); |
||||||
|
GradientDrawable centerItemPressedDrawable = new GradientDrawable(); |
||||||
|
centerItemPressedDrawable.setColor(mPressedBackgroundColor); |
||||||
|
GradientDrawable centerItemNormalDrawable = new GradientDrawable(); |
||||||
|
centerItemNormalDrawable.setColor(Color.TRANSPARENT); |
||||||
|
centerItemBackground.addState(new int[]{android.R.attr.state_pressed}, centerItemPressedDrawable); |
||||||
|
centerItemBackground.addState(new int[]{}, centerItemNormalDrawable); |
||||||
|
return centerItemBackground; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 刷新文本颜色状态列表 |
||||||
|
* |
||||||
|
* @param pressedTextColor 按下文本颜色 |
||||||
|
* @param normalTextColor 正常状态下文本颜色 |
||||||
|
*/ |
||||||
|
private void refreshTextColorStateList(int pressedTextColor, int normalTextColor) { |
||||||
|
int[][] states = new int[2][]; |
||||||
|
states[0] = new int[]{android.R.attr.state_pressed}; |
||||||
|
states[1] = new int[]{}; |
||||||
|
int[] colors = new int[]{pressedTextColor, normalTextColor}; |
||||||
|
mTextColorStateList = new ColorStateList(states, colors); |
||||||
|
} |
||||||
|
|
||||||
|
public void hidePopupListWindow() { |
||||||
|
if (mContext instanceof Activity && ((Activity) mContext).isFinishing()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (mPopupWindow != null && mPopupWindow.isShowing()) { |
||||||
|
mPopupWindow.dismiss(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public View getIndicatorView() { |
||||||
|
return mIndicatorView; |
||||||
|
} |
||||||
|
|
||||||
|
public View getDefaultIndicatorView(Context context) { |
||||||
|
return getTriangleIndicatorView(context, dp2px(16), dp2px(8), DEFAULT_NORMAL_BACKGROUND_COLOR); |
||||||
|
} |
||||||
|
|
||||||
|
public View getTriangleIndicatorView(Context context, final float widthPixel, final float heightPixel, |
||||||
|
final int color) { |
||||||
|
ImageView indicator = new ImageView(context); |
||||||
|
Drawable drawable = new Drawable() { |
||||||
|
@Override |
||||||
|
public void draw(Canvas canvas) { |
||||||
|
Path path = new Path(); |
||||||
|
Paint paint = new Paint(); |
||||||
|
paint.setColor(color); |
||||||
|
paint.setStyle(Paint.Style.FILL); |
||||||
|
if (!mIsShowBottom) { |
||||||
|
//这里画的倒三角
|
||||||
|
path.moveTo(0f, 0f); |
||||||
|
path.lineTo(widthPixel, 0f); |
||||||
|
path.lineTo(widthPixel / 2, heightPixel); |
||||||
|
//将图像封闭,这里path.close()等同于 path.moveTo(widthPixel / 2, heightPixel);path.lineTo(widthPixel, 0);
|
||||||
|
path.close(); |
||||||
|
} else { |
||||||
|
//正三角
|
||||||
|
path.moveTo(0f, heightPixel); |
||||||
|
path.lineTo(widthPixel, heightPixel); |
||||||
|
path.lineTo(widthPixel / 2, 0); |
||||||
|
path.close(); |
||||||
|
} |
||||||
|
canvas.drawPath(path, paint); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setAlpha(int alpha) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setColorFilter(ColorFilter colorFilter) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getOpacity() { |
||||||
|
return PixelFormat.TRANSLUCENT; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getIntrinsicWidth() { |
||||||
|
return (int) widthPixel; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getIntrinsicHeight() { |
||||||
|
return (int) heightPixel; |
||||||
|
} |
||||||
|
}; |
||||||
|
indicator.setImageDrawable(drawable); |
||||||
|
return indicator; |
||||||
|
} |
||||||
|
|
||||||
|
public void setIndicatorView(View indicatorView) { |
||||||
|
this.mIndicatorView = indicatorView; |
||||||
|
} |
||||||
|
|
||||||
|
public void setIndicatorSize(int widthPixel, int heightPixel) { |
||||||
|
this.mIndicatorWidth = widthPixel; |
||||||
|
this.mIndicatorHeight = heightPixel; |
||||||
|
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(mIndicatorWidth, mIndicatorHeight); |
||||||
|
layoutParams.gravity = Gravity.CENTER; |
||||||
|
if (mIndicatorView != null) { |
||||||
|
mIndicatorView.setLayoutParams(layoutParams); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int getNormalTextColor() { |
||||||
|
return mNormalTextColor; |
||||||
|
} |
||||||
|
|
||||||
|
public void setNormalTextColor(int normalTextColor) { |
||||||
|
this.mNormalTextColor = normalTextColor; |
||||||
|
refreshTextColorStateList(mPressedTextColor, mNormalTextColor); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPressedTextColor() { |
||||||
|
return mPressedTextColor; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPressedTextColor(int pressedTextColor) { |
||||||
|
this.mPressedTextColor = pressedTextColor; |
||||||
|
refreshTextColorStateList(mPressedTextColor, mNormalTextColor); |
||||||
|
} |
||||||
|
|
||||||
|
public float getTextSize() { |
||||||
|
return mTextSize; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTextSize(float textSizePixel) { |
||||||
|
this.mTextSize = textSizePixel; |
||||||
|
} |
||||||
|
|
||||||
|
public int getTextPaddingLeft() { |
||||||
|
return mTextPaddingLeft; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTextPaddingLeft(int textPaddingLeft) { |
||||||
|
this.mTextPaddingLeft = textPaddingLeft; |
||||||
|
} |
||||||
|
|
||||||
|
public int getTextPaddingTop() { |
||||||
|
return mTextPaddingTop; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTextPaddingTop(int textPaddingTop) { |
||||||
|
this.mTextPaddingTop = textPaddingTop; |
||||||
|
} |
||||||
|
|
||||||
|
public int getTextPaddingRight() { |
||||||
|
return mTextPaddingRight; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTextPaddingRight(int textPaddingRight) { |
||||||
|
this.mTextPaddingRight = textPaddingRight; |
||||||
|
} |
||||||
|
|
||||||
|
public int getTextPaddingBottom() { |
||||||
|
return mTextPaddingBottom; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTextPaddingBottom(int textPaddingBottom) { |
||||||
|
this.mTextPaddingBottom = textPaddingBottom; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTextPadding(int left, int top, int right, int bottom) { |
||||||
|
this.mTextPaddingLeft = left; |
||||||
|
this.mTextPaddingTop = top; |
||||||
|
this.mTextPaddingRight = right; |
||||||
|
this.mTextPaddingBottom = bottom; |
||||||
|
} |
||||||
|
|
||||||
|
public int getNormalBackgroundColor() { |
||||||
|
return mNormalBackgroundColor; |
||||||
|
} |
||||||
|
|
||||||
|
public void setNormalBackgroundColor(int normalBackgroundColor) { |
||||||
|
this.mNormalBackgroundColor = normalBackgroundColor; |
||||||
|
refreshBackgroundOrRadiusStateList(); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPressedBackgroundColor() { |
||||||
|
return mPressedBackgroundColor; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPressedBackgroundColor(int pressedBackgroundColor) { |
||||||
|
this.mPressedBackgroundColor = pressedBackgroundColor; |
||||||
|
refreshBackgroundOrRadiusStateList(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setShowBottom(boolean isShowBottom) { |
||||||
|
this.mIsShowBottom = isShowBottom; |
||||||
|
} |
||||||
|
|
||||||
|
public void setShowTouchLocation(boolean showTouchLocation) { |
||||||
|
mIsShowTouchLocation = showTouchLocation; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFocusable(boolean mIsFocusable) { |
||||||
|
this.mIsFocusable = mIsFocusable; |
||||||
|
} |
||||||
|
|
||||||
|
public int getBackgroundCornerRadius() { |
||||||
|
return mBackgroundCornerRadius; |
||||||
|
} |
||||||
|
|
||||||
|
public void setBackgroundCornerRadius(int backgroundCornerRadiusPixel) { |
||||||
|
this.mBackgroundCornerRadius = backgroundCornerRadiusPixel; |
||||||
|
refreshBackgroundOrRadiusStateList(); |
||||||
|
} |
||||||
|
|
||||||
|
public int getDividerColor() { |
||||||
|
return mDividerColor; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDividerColor(int dividerColor) { |
||||||
|
this.mDividerColor = dividerColor; |
||||||
|
} |
||||||
|
|
||||||
|
public int getDividerWidth() { |
||||||
|
return mDividerWidth; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDividerWidth(int dividerWidthPixel) { |
||||||
|
this.mDividerWidth = dividerWidthPixel; |
||||||
|
} |
||||||
|
|
||||||
|
public int getDividerHeight() { |
||||||
|
return mDividerHeight; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDividerHeight(int dividerHeightPixel) { |
||||||
|
this.mDividerHeight = dividerHeightPixel; |
||||||
|
} |
||||||
|
|
||||||
|
public void setmReversalHeight(float mReversalHeight) { |
||||||
|
this.mReversalHeight = mReversalHeight; |
||||||
|
} |
||||||
|
|
||||||
|
public Resources getResources() { |
||||||
|
if (mContext == null) { |
||||||
|
return Resources.getSystem(); |
||||||
|
} else { |
||||||
|
return mContext.getResources(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private int getViewWidth(View view) { |
||||||
|
// 1、UNSPECIFIED,不限定。意思就是,子View想要多大,我就可以给你多大,你放心大胆的measure吧,不用管其他的。也不用管我传递给你的尺寸值。(其实Android高版本中推荐,只要是这个模式,尺寸设置为0)
|
||||||
|
//
|
||||||
|
// 2、EXACTLY,精确的。意思就是,根据我当前的状况,结合你指定的尺寸参数来考虑,你就应该是这个尺寸,具体大小在MeasureSpec的尺寸属性中,自己去查看吧,你也不要管你的content有多大了,就用这个尺寸吧。
|
||||||
|
//
|
||||||
|
// 3、AT_MOST,最多的。意思就是,根据我当前的情况,结合你指定的尺寸参数来考虑,在不超过我给你限定的尺寸的前提下,你测量一个恰好能包裹你内容的尺寸就可以了。
|
||||||
|
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); |
||||||
|
return view.getMeasuredWidth(); |
||||||
|
} |
||||||
|
|
||||||
|
private int getViewHeight(View view) { |
||||||
|
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); |
||||||
|
return view.getMeasuredHeight(); |
||||||
|
} |
||||||
|
|
||||||
|
public int dp2px(float value) { |
||||||
|
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, |
||||||
|
value, getResources().getDisplayMetrics()); |
||||||
|
} |
||||||
|
|
||||||
|
public int sp2px(float value) { |
||||||
|
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, |
||||||
|
value, getResources().getDisplayMetrics()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 回调监听器 |
||||||
|
*/ |
||||||
|
public interface PopupListListener { |
||||||
|
boolean showPopupList(View adapterView, View contextView, int contextPosition); |
||||||
|
|
||||||
|
void onPopupListClick(View contextView, int contextPosition, int position); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,11 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="24" |
||||||
|
android:viewportHeight="24"> |
||||||
|
|
||||||
|
<path |
||||||
|
android:fillColor="#595757" |
||||||
|
android:pathData="M12,4h8v8c0,4.418-3.582,8-8,8s-8-3.582-8-8S7.582,4,12,4z" /> |
||||||
|
</vector> |
@ -0,0 +1,11 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="24" |
||||||
|
android:viewportHeight="24"> |
||||||
|
|
||||||
|
<path |
||||||
|
android:fillColor="#595757" |
||||||
|
android:pathData="M12,4.208H4v8c0,4.418,3.582,8,8,8s8-3.582,8-8S16.418,4.208,12,4.208z" /> |
||||||
|
</vector> |
@ -0,0 +1,9 @@ |
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="1024" |
||||||
|
android:viewportHeight="1024"> |
||||||
|
<path |
||||||
|
android:pathData="M733.86,791.95c0,26.57 -21.63,48.2 -48.2,48.2L338.35,840.15c-26.57,0 -48.2,-21.63 -48.2,-48.2L290.14,280.26h443.71v511.69zM386.55,193.74c0,-5.56 4.33,-9.89 9.89,-9.89h231.74c5.56,0 9.89,4.33 9.89,9.89v29.05L386.55,222.78L386.55,193.74zM878.46,222.78L695.54,222.78L695.54,193.74c0,-37.08 -30.28,-67.36 -67.36,-67.36h-231.74c-37.08,0 -67.36,30.28 -67.36,67.36v29.05L145.54,222.78C129.47,222.78 116.49,235.76 116.49,251.83s12.98,29.05 29.05,29.05h86.52v511.07c0,58.71 47.58,106.29 106.29,106.29h347.31c58.71,0 106.29,-47.58 106.29,-106.29L791.95,280.26h86.52c16.07,0 29.05,-12.98 29.05,-29.05s-12.98,-28.43 -29.05,-28.43zM512,753.01c16.07,0 29.05,-12.98 29.05,-29.05v-308.99c0,-16.07 -12.98,-29.05 -29.05,-29.05s-29.05,12.98 -29.05,29.05v308.99c0,16.07 12.98,29.05 29.05,29.05m-135.34,0c16.07,0 29.05,-12.98 29.05,-29.05v-308.99c0,-16.07 -12.98,-29.05 -29.05,-29.05s-29.05,12.98 -29.05,29.05v308.99c0.62,16.07 13.6,29.05 29.05,29.05m270.68,0c16.07,0 29.05,-12.98 29.05,-29.05v-308.99c0,-16.07 -12.98,-29.05 -29.05,-29.05s-29.05,12.98 -29.05,29.05v308.99c0,16.07 12.98,29.05 29.05,29.05" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
</vector> |
@ -0,0 +1,15 @@ |
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="1024" |
||||||
|
android:viewportHeight="1024"> |
||||||
|
<path |
||||||
|
android:pathData="M778.75,845.31H245.25c-53.76,0 -97.28,-43.52 -97.28,-97.28V275.46c0,-53.76 43.52,-97.28 97.28,-97.28h131.07c17.92,0 35.33,8.19 46.59,22.02l57.34,69.12h303.62c50.69,0 91.65,40.96 91.65,91.65v387.07c0.51,53.76 -43.52,97.28 -96.77,97.28zM245.25,239.1c-19.97,0 -36.35,16.38 -36.35,36.35v472.58c0,19.97 16.38,36.35 36.35,36.35h533.5c19.97,0 36.35,-16.38 36.35,-36.35V360.96c0,-16.9 -13.82,-30.72 -31.23,-30.72H480.77c-17.92,0 -35.33,-8.19 -46.59,-22.02L376.83,239.1H245.25z" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
<path |
||||||
|
android:pathData="M614.4,584.4c-8.7,0 -17.4,-3.4 -24.2,-10L512,496.2l-78.2,78.2c-13.3,13.4 -35,13.4 -48.2,0 -13.4,-13.4 -13.4,-35 0,-48.2L488,423.8c13.3,-13.4 35,-13.4 48.2,0l102.4,102.4c13.4,13.4 13.4,35 0,48.2 -6.8,6.8 -15.5,10 -24.2,10zM614.4,584.4" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
<path |
||||||
|
android:pathData="M512.51,424.45c16.9,0 30.21,13.82 30.21,30.21v211.97c0,16.9 -13.82,30.21 -30.21,30.21 -16.9,0 -30.21,-13.82 -30.21,-30.21V454.66c0,-16.9 13.82,-30.21 30.21,-30.21z" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
</vector> |
@ -0,0 +1,15 @@ |
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="1024" |
||||||
|
android:viewportHeight="1024"> |
||||||
|
<path |
||||||
|
android:pathData="M778.75,845.31H245.25c-53.76,0 -97.28,-43.52 -97.28,-97.28V275.46c0,-53.76 43.52,-97.28 97.28,-97.28h131.07c17.92,0 35.33,8.19 46.59,22.02l57.34,69.12h303.62c50.69,0 91.65,40.96 91.65,91.65v387.07c0.51,53.76 -43.52,97.28 -96.77,97.28zM245.25,239.1c-19.97,0 -36.35,16.38 -36.35,36.35v472.58c0,19.97 16.38,36.35 36.35,36.35h533.5c19.97,0 36.35,-16.38 36.35,-36.35V360.96c0,-16.9 -13.82,-30.72 -31.23,-30.72H480.77c-17.92,0 -35.33,-8.19 -46.59,-22.02L376.83,239.1H245.25z" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
<path |
||||||
|
android:pathData="M421.89,545.79c7.68,0 15.36,3.07 21.5,8.7l69.63,69.63 69.63,-69.63c11.78,-11.78 31.23,-11.78 43.01,0 11.78,11.78 11.78,31.23 0,43.01l-91.14,91.14c-11.78,11.78 -31.23,11.78 -43.01,0l-91.14,-91.14c-11.78,-11.78 -11.78,-31.23 0,-43.01 5.63,-6.14 13.82,-8.7 21.5,-8.7z" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
<path |
||||||
|
android:pathData="M512.51,424.45c16.9,0 30.21,13.82 30.21,30.21v211.97c0,16.9 -13.82,30.21 -30.21,30.21 -16.9,0 -30.21,-13.82 -30.21,-30.21V454.66c0,-16.9 13.82,-30.21 30.21,-30.21z" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
</vector> |
@ -0,0 +1,9 @@ |
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="1024" |
||||||
|
android:viewportHeight="1024"> |
||||||
|
<path |
||||||
|
android:pathData="M410.11,449.31h-55.92l-39.94,-107.18L151.1,342.13l-37.55,107.18h-55.98l149.22,-391.68h54.1L410.17,449.31zM298.61,297.81l-59.16,-162.76a182.39,182.39 0,0 1,-6.14 -27.31L232.11,107.75a146.66,146.66 0,0 1,-6.26 27.31L167.03,297.81h131.47zM662.93,967.11v-395.95h137.56c41.07,0 73.96,8.31 98.42,24.92 24.63,16.67 36.92,38.68 36.92,66.1 0,21.79 -7.34,41.02 -21.96,57.8 -14.62,16.73 -34.7,28.44 -60.3,35.56v1.02c31.86,3.02 57.29,13.2 76.34,30.55 19.06,17.35 28.5,39.25 28.5,65.82 0,34.13 -14.45,61.67 -43.35,82.72 -28.79,20.99 -65.82,31.46 -110.93,31.46h-141.2zM723.46,615.88v124.02h55.01c29.18,0 52.17,-6.09 68.72,-18.03 16.33,-11.32 25.71,-30.15 25.03,-49.95 0,-37.32 -29.41,-55.92 -88.23,-55.92h-60.53v-0.11zM723.46,784.38v138.01h72.48c31.57,0 56.04,-6.14 73.39,-18.55a59.73,59.73 0,0 0,25.71 -51.48c0,-45.34 -36.41,-67.98 -109.11,-67.98h-62.46zM440.15,864.2l6.49,-38.17a353.62,353.62 0,0 1,-265.39 -311.98h64.68a291.9,291.9 0,0 0,212.31 248.55l9.73,-54.39 121.06,102.29 -148.88,53.7z" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
</vector> |
@ -0,0 +1,9 @@ |
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="1024" |
||||||
|
android:viewportHeight="1024"> |
||||||
|
<path |
||||||
|
android:pathData="M298.24,469.33L128,640l170.24,170.67v-128h299.09v-85.33H298.24v-128zM896,384L725.76,213.33v128H426.67v85.33H725.76v128L896,384z" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
</vector> |
@ -0,0 +1,12 @@ |
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="1024" |
||||||
|
android:viewportHeight="1024"> |
||||||
|
<path |
||||||
|
android:pathData="M618.92,469.52c-22.9,23.46 -22.9,61.5 0,84.97l116.95,128.1c22.91,23.46 60.05,23.46 82.96,0 22.9,-23.46 22.9,-61.5 0,-84.97l-75.57,-85.62 75.57,-85.62c22.9,-23.47 22.9,-61.51 0,-84.97 -22.91,-23.47 -60.05,-23.47 -82.96,0L618.92,469.52v-0z" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
<path |
||||||
|
android:pathData="M705.45,857.03L329.51,512l375.94,-345.03c22.91,-23.47 22.91,-61.51 0,-84.97 -22.9,-23.47 -60.04,-23.47 -82.96,0L205.17,469.52c-22.91,23.46 -22.91,61.5 0,84.97L622.49,942c22.91,23.46 60.05,23.46 82.95,0 22.91,-23.46 22.91,-61.5 0,-84.97z" |
||||||
|
android:fillColor="#FFFFFF"/> |
||||||
|
</vector> |
@ -0,0 +1,16 @@ |
|||||||
|
<?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="match_parent" |
||||||
|
android:orientation="vertical"> |
||||||
|
|
||||||
|
<include layout="@layout/toolbar"/> |
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView |
||||||
|
android:id="@+id/rv_rule_list" |
||||||
|
android:background="@color/colorForeground" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent"/> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,221 @@ |
|||||||
|
<?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="match_parent" |
||||||
|
android:background="@color/colorForeground" |
||||||
|
android:orientation="vertical"> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="vertical" |
||||||
|
android:padding="5dp"> |
||||||
|
|
||||||
|
|
||||||
|
<TextView |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:gravity="center" |
||||||
|
android:paddingTop="10dp" |
||||||
|
android:text="@string/content_replace" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:textSize="@dimen/text_medium_size" /> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:padding="5dp"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:text="@string/summary" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:textSize="@dimen/text_normal_size" /> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText |
||||||
|
android:id="@+id/et_rule_desc" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:hint="@string/summary_tip" |
||||||
|
android:maxLines="3" |
||||||
|
android:paddingStart="10dp" |
||||||
|
android:paddingEnd="10dp" |
||||||
|
android:textSize="@dimen/text_small_size" /> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:padding="5dp"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:text="@string/replace_rule_old" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:textSize="@dimen/text_normal_size" /> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText |
||||||
|
android:id="@+id/et_rule_old" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:hint="@string/replace_rule_old_tip" |
||||||
|
android:maxLines="3" |
||||||
|
android:paddingStart="10dp" |
||||||
|
android:paddingEnd="10dp" |
||||||
|
android:textSize="@dimen/text_small_size" /> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<CheckBox |
||||||
|
android:id="@+id/cb_use_regex" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="20dp" |
||||||
|
android:text="@string/replace_use_regex" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:theme="@style/MyCheckBox" /> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:padding="5dp"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:text="@string/replace_rule_new" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:textSize="@dimen/text_normal_size" /> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText |
||||||
|
android:id="@+id/et_rule_new" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:hint="@string/replace_rule_new_tip" |
||||||
|
android:maxLines="3" |
||||||
|
android:paddingStart="10dp" |
||||||
|
android:paddingEnd="10dp" |
||||||
|
android:textSize="@dimen/text_small_size" /> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:padding="5dp"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:text="@string/use_to_source" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:textSize="@dimen/text_normal_size" /> |
||||||
|
|
||||||
|
<RelativeLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText |
||||||
|
android:id="@+id/et_rule_source" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_alignParentStart="true" |
||||||
|
android:layout_centerVertical="true" |
||||||
|
android:hint="@string/use_to_source_tip" |
||||||
|
android:maxLines="3" |
||||||
|
android:paddingStart="10dp" |
||||||
|
android:paddingEnd="10dp" |
||||||
|
android:textSize="@dimen/text_small_size" /> |
||||||
|
|
||||||
|
<Button |
||||||
|
android:id="@+id/bt_select_source" |
||||||
|
android:layout_width="48dp" |
||||||
|
android:layout_height="35dp" |
||||||
|
android:layout_alignParentEnd="true" |
||||||
|
android:text="@string/select" |
||||||
|
android:textSize="@dimen/text_default_size" /> |
||||||
|
</RelativeLayout> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:padding="5dp"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:text="@string/use_to_book" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:textSize="@dimen/text_normal_size" /> |
||||||
|
|
||||||
|
<RelativeLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText |
||||||
|
android:id="@+id/et_rule_book" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_alignParentStart="true" |
||||||
|
android:layout_centerVertical="true" |
||||||
|
android:hint="@string/use_to_book_tip" |
||||||
|
android:maxLines="3" |
||||||
|
android:paddingStart="10dp" |
||||||
|
android:paddingEnd="10dp" |
||||||
|
android:textSize="@dimen/text_small_size" /> |
||||||
|
|
||||||
|
<Button |
||||||
|
android:id="@+id/bt_select_book" |
||||||
|
android:layout_width="48dp" |
||||||
|
android:layout_height="35dp" |
||||||
|
android:layout_alignParentEnd="true" |
||||||
|
android:text="@string/select" |
||||||
|
android:textSize="@dimen/text_default_size" /> |
||||||
|
</RelativeLayout> |
||||||
|
</LinearLayout> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<View |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="0.5dp" |
||||||
|
android:background="@color/colorBackground" /> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="horizontal"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/tv_cancel" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="50dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:background="@drawable/selector_common_bg" |
||||||
|
android:gravity="center" |
||||||
|
android:text="@string/cancel" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:textSize="16sp" /> |
||||||
|
|
||||||
|
<View |
||||||
|
android:layout_width="0.5dp" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:background="@color/colorBackground" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/tv_confirm" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="50dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:background="@drawable/selector_common_bg" |
||||||
|
android:gravity="center" |
||||||
|
android:text="@string/confirm" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:textSize="16sp" /> |
||||||
|
</LinearLayout> |
||||||
|
</LinearLayout> |
@ -0,0 +1,79 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<com.mcxtzhang.swipemenulib.SwipeMenuLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="50dp" |
||||||
|
android:clickable="true" |
||||||
|
android:paddingBottom="1dp" |
||||||
|
app:ios="false" |
||||||
|
app:leftSwipe="true" |
||||||
|
app:swipeEnable="true" |
||||||
|
android:focusable="true"> |
||||||
|
|
||||||
|
<RelativeLayout |
||||||
|
android:id="@+id/rl_content" |
||||||
|
android:paddingStart="10dp" |
||||||
|
android:paddingEnd="10dp" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:background="?android:attr/selectableItemBackground"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/tv_rule_summary" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:layout_toStartOf="@+id/iv_swipe_left" |
||||||
|
android:textColor="@color/textPrimary" |
||||||
|
android:maxLines="1" |
||||||
|
android:ellipsize="end" |
||||||
|
android:layout_alignParentStart="true" |
||||||
|
android:gravity="center_vertical" |
||||||
|
android:text="@string/summary" /> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView |
||||||
|
android:id="@+id/iv_swipe_left" |
||||||
|
android:layout_width="13dp" |
||||||
|
android:layout_height="13dp" |
||||||
|
android:layout_centerVertical="true" |
||||||
|
android:layout_alignParentEnd="true" |
||||||
|
app:tint="@color/textAssist" |
||||||
|
app:srcCompat="@drawable/ic_swipe_left"/> |
||||||
|
|
||||||
|
</RelativeLayout> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 以下都是侧滑菜单的内容依序排列 --> |
||||||
|
<!--<Button |
||||||
|
android:id="@+id/bt_top" |
||||||
|
android:layout_width="65dp" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:background="@color/md_purple_500" |
||||||
|
android:text="@string/top" |
||||||
|
android:textColor="@android:color/white"/>--> |
||||||
|
<Button |
||||||
|
android:id="@+id/bt_ban" |
||||||
|
android:layout_width="65dp" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:background="@color/md_blue_500" |
||||||
|
android:text="@string/ban" |
||||||
|
android:textColor="@android:color/white"/> |
||||||
|
<Button |
||||||
|
android:id="@+id/bt_share" |
||||||
|
android:layout_width="65dp" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:background="@color/md_yellow_800" |
||||||
|
android:clickable="true" |
||||||
|
android:text="@string/share" |
||||||
|
android:textColor="@android:color/white" |
||||||
|
android:focusable="true" /> |
||||||
|
|
||||||
|
<Button |
||||||
|
android:id="@+id/btnDelete" |
||||||
|
android:layout_width="65dp" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:background="@color/md_red_500" |
||||||
|
android:text="@string/delete" |
||||||
|
android:textColor="@android:color/white"/> |
||||||
|
|
||||||
|
</com.mcxtzhang.swipemenulib.SwipeMenuLayout> |
@ -0,0 +1,29 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
|
tools:showIn="bottom_navigation_view"> |
||||||
|
|
||||||
|
<item |
||||||
|
android:id="@+id/action_add_rule" |
||||||
|
android:icon="@drawable/ic_add" |
||||||
|
android:title="@string/add_rule"/> |
||||||
|
<item |
||||||
|
android:id="@+id/action_import" |
||||||
|
android:icon="@drawable/ic_import" |
||||||
|
android:title="@string/import_rule"/> |
||||||
|
|
||||||
|
<item |
||||||
|
android:id="@+id/action_export" |
||||||
|
android:icon="@drawable/ic_export" |
||||||
|
android:title="@string/export_all"/> |
||||||
|
<item |
||||||
|
android:id="@+id/action_reverse" |
||||||
|
android:icon="@drawable/ic_reverse" |
||||||
|
android:title="@string/reverse_rule"/> |
||||||
|
|
||||||
|
<item |
||||||
|
android:id="@+id/action_delete" |
||||||
|
android:icon="@drawable/ic_delete" |
||||||
|
android:title="@string/delete_ban_rule"/> |
||||||
|
|
||||||
|
</menu> |
@ -1,2 +1,2 @@ |
|||||||
#Sat Jan 09 20:56:54 CST 2021 |
#Tue Jan 19 16:58:48 CST 2021 |
||||||
VERSION_CODE=178 |
VERSION_CODE=179 |
||||||
|
Loading…
Reference in new issue